diff --git a/api/go.mod b/api/go.mod
index 897ad9a5b..bce9e6180 100644
--- a/api/go.mod
+++ b/api/go.mod
@@ -15,6 +15,4 @@ require (
sigs.k8s.io/yaml v1.2.0
)
-replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
-
replace sigs.k8s.io/kustomize/kyaml => ../kyaml
diff --git a/api/go.sum b/api/go.sum
index ae5c8ddb3..5055de671 100644
--- a/api/go.sum
+++ b/api/go.sum
@@ -217,8 +217,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
diff --git a/cmd/config/go.mod b/cmd/config/go.mod
index 3046eba39..cc78147b4 100644
--- a/cmd/config/go.mod
+++ b/cmd/config/go.mod
@@ -19,6 +19,4 @@ require (
sigs.k8s.io/kustomize/kyaml v0.10.20
)
-replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
-
replace sigs.k8s.io/kustomize/kyaml => ../../kyaml
diff --git a/cmd/config/go.sum b/cmd/config/go.sum
index 8fc6cbf50..06b87c52d 100644
--- a/cmd/config/go.sum
+++ b/cmd/config/go.sum
@@ -237,8 +237,9 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
diff --git a/cmd/config/internal/commands/cmdwrap_test.go b/cmd/config/internal/commands/cmdwrap_test.go
index 988b644fb..fb4ead8dd 100644
--- a/cmd/config/internal/commands/cmdwrap_test.go
+++ b/cmd/config/internal/commands/cmdwrap_test.go
@@ -117,8 +117,8 @@ items:
name: test
app: nginx
ports:
+ # This i the port.
- name: http
- # This i the port.
port: 8080
targetPort: 8080
`
@@ -169,8 +169,8 @@ items:
name: test
app: nginx
ports:
+ # This i the port.
- name: http
- # This i the port.
port: 8080
targetPort: 8080
`
@@ -269,8 +269,8 @@ items:
name: test
app: nginx
ports:
+ # This i the port.
- name: http
- # This i the port.
port: 8080
targetPort: 8080
`
diff --git a/cmd/config/internal/commands/merge3_test.go b/cmd/config/internal/commands/merge3_test.go
index 171aec4d7..c23176f5b 100644
--- a/cmd/config/internal/commands/merge3_test.go
+++ b/cmd/config/internal/commands/merge3_test.go
@@ -53,8 +53,7 @@ spec:
name: app-config
env:
- name: JAVA_OPTS
- value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
- -Djava.security.egd=file:/dev/./urandom
+ value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 5
`), 0600)
@@ -104,8 +103,7 @@ spec:
name: app-config
env:
- name: JAVA_OPTS
- value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
- -Djava.security.egd=file:/dev/./urandom
+ value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 20
`), 0600)
@@ -152,8 +150,7 @@ spec:
name: app-config
env:
- name: JAVA_OPTS
- value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
- -Djava.security.egd=file:/dev/./urandom
+ value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 5
`), 0600)
@@ -201,8 +198,7 @@ spec:
name: app-config
env:
- name: JAVA_OPTS
- value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap
- -Djava.security.egd=file:/dev/./urandom
+ value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -Djava.security.egd=file:/dev/./urandom
imagePullPolicy: Always
minReadySeconds: 20
`), 0600)
diff --git a/cmd/config/internal/commands/source_test.go b/cmd/config/internal/commands/source_test.go
index 717b22c4a..1fcad88d4 100644
--- a/cmd/config/internal/commands/source_test.go
+++ b/cmd/config/internal/commands/source_test.go
@@ -194,13 +194,8 @@ func TestSourceCommandJSON(t *testing.T) {
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
kind: ResourceList
items:
-- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo",
- "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f1.json'}},
- "spec": {"replicas": 1}}
-- {"apiVersion": "v1", "kind": "Abstraction", "metadata": {"name": "foo", "annotations": {
- "config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n",
- "config.kubernetes.io/local-config": "true", config.kubernetes.io/index: '0',
- config.kubernetes.io/path: 'f2.json'}}, "spec": {"replicas": 3}}
+- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", "annotations": {"app": "nginx2", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f1.json'}}, "spec": {"replicas": 1}}
+- {"apiVersion": "v1", "kind": "Abstraction", "metadata": {"name": "foo", "annotations": {"config.kubernetes.io/function": "container:\n image: gcr.io/example/reconciler:v1\n", "config.kubernetes.io/local-config": "true", config.kubernetes.io/index: '0', config.kubernetes.io/path: 'f2.json'}}, "spec": {"replicas": 3}}
`, b.String()) {
return
}
@@ -307,9 +302,7 @@ func TestSourceCommandJSON_Stdin(t *testing.T) {
if !assert.Equal(t, `apiVersion: config.kubernetes.io/v1alpha1
kind: ResourceList
items:
-- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo",
- "annotations": {"app": "nginx2", config.kubernetes.io/index: '0'}}, "spec": {
- "replicas": 1}}
+- {"kind": "Deployment", "metadata": {"labels": {"app": "nginx2"}, "name": "foo", "annotations": {"app": "nginx2", config.kubernetes.io/index: '0'}}, "spec": {"replicas": 1}}
`, out.String()) {
return
}
diff --git a/cmd/depprobcheck/go.sum b/cmd/depprobcheck/go.sum
index ddd5bfeb3..b4839941a 100644
--- a/cmd/depprobcheck/go.sum
+++ b/cmd/depprobcheck/go.sum
@@ -76,8 +76,6 @@ github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
-github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
diff --git a/cmd/pluginator/go.sum b/cmd/pluginator/go.sum
index 8a9507ce1..0e31bbef8 100644
--- a/cmd/pluginator/go.sum
+++ b/cmd/pluginator/go.sum
@@ -222,7 +222,6 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
diff --git a/functions/examples/application-cr/image/go.mod b/functions/examples/application-cr/image/go.mod
index c5009629d..502fb49f7 100644
--- a/functions/examples/application-cr/image/go.mod
+++ b/functions/examples/application-cr/image/go.mod
@@ -3,7 +3,7 @@ module sigs.k8s.io/kustomize/functions/examples/application-cr
go 1.16
require (
- github.com/evanphx/json-patch v4.11.0+incompatible
+ github.com/evanphx/json-patch v4.11.0+incompatible // indirect
k8s.io/apimachinery v0.18.3
sigs.k8s.io/application v0.8.2
sigs.k8s.io/kustomize/kyaml v0.7.1
diff --git a/functions/examples/application-cr/image/go.sum b/functions/examples/application-cr/image/go.sum
index 1dc4c4dcd..95162e183 100644
--- a/functions/examples/application-cr/image/go.sum
+++ b/functions/examples/application-cr/image/go.sum
@@ -75,7 +75,6 @@ github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkg
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.11.0+incompatible h1:glyUF9yIYtMHzn8xaKw5rMhdWcwsYV8dZHIq5567/xs=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
diff --git a/kyaml/Makefile b/kyaml/Makefile
index 6d06019a5..65707874e 100644
--- a/kyaml/Makefile
+++ b/kyaml/Makefile
@@ -40,10 +40,7 @@ lint: $(MYGOBIN)/golangci-lint
license: $(MYGOBIN)/addlicense
- $(MYGOBIN)/addlicense \
- -y 2021 \
- -c "The Kubernetes Authors." \
- -f LICENSE_TEMPLATE .
+ ( find . -type f -not -path "*/internal/forked/github.com/go-yaml*" -exec bash -c "$(MYGOBIN)/addlicense -y 2021 -c 'The Kubernetes Authors.' -f LICENSE_TEMPLATE {}" ";" )
test:
go test -cover ./...
@@ -52,10 +49,10 @@ fix:
go fix ./...
fmt:
- go fmt ./...
+ go fmt $(shell go list ./... | grep -v "/kyaml/internal/forked/github.com/go-yaml/yaml")
tidy:
go mod tidy
vet:
- go vet ./...
+ go vet $(shell go list ./... | grep -v "/kyaml/internal/forked/github.com/go-yaml/yaml")
diff --git a/kyaml/filesys/filesystem_test.go b/kyaml/filesys/filesystem_test.go
index fd8ab2506..9599e6c45 100644
--- a/kyaml/filesys/filesystem_test.go
+++ b/kyaml/filesys/filesystem_test.go
@@ -1,3 +1,6 @@
+// Copyright 2021 The Kubernetes Authors.
+// SPDX-License-Identifier: Apache-2.0
+
package filesys
import (
diff --git a/kyaml/go.mod b/kyaml/go.mod
index d5f040200..61b581ab8 100644
--- a/kyaml/go.mod
+++ b/kyaml/go.mod
@@ -16,8 +16,8 @@ require (
github.com/stretchr/testify v1.5.1
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5
+ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
gopkg.in/yaml.v2 v2.4.0
- gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e
)
@@ -31,5 +31,3 @@ require (
// replace github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547 => github.com/golangci/gosec v0.0.0-20190211064107-66fb7fc33547
// replace github.com/golangci/lint-1 v0.0.0-20180610141402-ee948d087217 => github.com/golangci/lint-1 v0.0.0-20190420132249-ee948d087217
// replace mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34 => mvdan.cc/unparam v0.0.0-20190209190245-fbb59629db34
-
-replace gopkg.in/yaml.v3 => gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
diff --git a/kyaml/go.sum b/kyaml/go.sum
index 6d1920b01..58f7342c0 100644
--- a/kyaml/go.sum
+++ b/kyaml/go.sum
@@ -218,8 +218,7 @@ gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
diff --git a/kyaml/internal/forked/README.md b/kyaml/internal/forked/README.md
new file mode 100644
index 000000000..ee26037bb
--- /dev/null
+++ b/kyaml/internal/forked/README.md
@@ -0,0 +1,11 @@
+# kyaml internal forks
+
+## qri-io/starlib
+
+This code is used by the starlark runtime. We copied it in to reduce the dependencies being brought over to kubectl by the kustomize integration. Should it need updating, do so via manual copy-paste.
+
+## go-yaml/yaml
+
+This code is used extensively by kyaml. It is a copy of upstream at a particular revision that kubectl is using, with [a change we need](https://github.com/go-yaml/yaml/pull/753) cherry-picked on top. For background information on this problem, see https://github.com/kubernetes-sigs/kustomize/issues/3946.
+
+This copy was created using the [git subtree technique](https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec) and can be recreated on top of a new version of go-yaml v3 using the [update-go-yaml.sh](update-go-yaml.sh) script. Please note that there is nothing special about the fork directory, so copy-paste with manual edits will work just fine if you prefer.
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/.github/workflows/go.yaml b/kyaml/internal/forked/github.com/go-yaml/yaml/.github/workflows/go.yaml
new file mode 100644
index 000000000..d2bb00b07
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/.github/workflows/go.yaml
@@ -0,0 +1,61 @@
+---
+name: Go
+on: [push, pull_request]
+jobs:
+ test:
+ name: Test
+ runs-on: ubuntu-20.04
+ strategy:
+ fail-fast: false
+ matrix:
+ go:
+ - "1.5"
+ - "1.6"
+ - "1.7"
+ - "1.8"
+ - "1.9"
+ - "1.10"
+ - "1.11"
+ - "1.12"
+ - "1.13"
+ - "1.14"
+ - "1.15"
+ - "1.16.0-beta1"
+ - "tip"
+ env:
+ GOPATH: ${{ github.workspace }}/go
+ steps:
+ - name: Check out code into the Go module directory
+ uses: actions/checkout@v2
+ with:
+ path: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3
+ - name: Set up Go ${{ matrix.go }}
+ if: matrix.go != 'tip'
+ uses: actions/setup-go@v2
+ with:
+ go-version: ${{ matrix.go }}
+ stable: false
+ - name: Set up Go ${{ matrix.go }}
+ if: matrix.go == 'tip'
+ run: |
+ export GOROOT_BOOTSTRAP=`go env GOROOT`
+ export GOROOT=$HOME/gotip
+ mkdir $HOME/gotip
+ cd $HOME/gotip
+
+ curl -s 'https://go.googlesource.com/go/+/refs/heads/master?format=JSON' | awk '/"commit"/{print substr($2,2,40);exit}' >HEAD
+ awk '{printf("gotip-%s",substr($0,0,7))}'
VERSION
+
+ curl -s -o go.tar.gz https://go.googlesource.com/go/+archive/`cat HEAD`.tar.gz
+ tar xfz go.tar.gz
+
+ cd src
+ bash make.bash
+
+ echo "GOROOT=$GOROOT" >> $GITHUB_ENV
+ echo "$GOROOT/bin" >> $GITHUB_PATH
+ - run: go version
+ - run: go get -t ./...
+ working-directory: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3
+ - run: go test .
+ working-directory: ${{ github.workspace }}/go/src/gopkg.in/yaml.v3
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/.github/workflows/semgrep.yaml b/kyaml/internal/forked/github.com/go-yaml/yaml/.github/workflows/semgrep.yaml
new file mode 100644
index 000000000..200c00a5a
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/.github/workflows/semgrep.yaml
@@ -0,0 +1,16 @@
+---
+name: Semgrep
+on: [push, pull_request]
+jobs:
+ semgrep:
+ name: semgrep
+ runs-on: ubuntu-20.04
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Semgrep
+ id: semgrep
+ uses: returntocorp/semgrep-action@v1
+ with:
+ config: p/dgryski.semgrep-go
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE b/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE
new file mode 100644
index 000000000..2683e4bb1
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/LICENSE
@@ -0,0 +1,50 @@
+
+This project is covered by two different licenses: MIT and Apache.
+
+#### MIT License ####
+
+The following files were ported to Go from C files of libyaml, and thus
+are still covered by their original MIT license, with the additional
+copyright staring in 2011 when the project was ported over:
+
+ apic.go emitterc.go parserc.go readerc.go scannerc.go
+ writerc.go yamlh.go yamlprivateh.go
+
+Copyright (c) 2006-2010 Kirill Simonov
+Copyright (c) 2006-2011 Kirill Simonov
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+### Apache License ###
+
+All the remaining project files are covered by the Apache license:
+
+Copyright (c) 2011-2019 Canonical Ltd
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE b/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE
new file mode 100644
index 000000000..866d74a7a
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/NOTICE
@@ -0,0 +1,13 @@
+Copyright 2011-2016 Canonical Ltd.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/README.md b/kyaml/internal/forked/github.com/go-yaml/yaml/README.md
new file mode 100644
index 000000000..08eb1babd
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/README.md
@@ -0,0 +1,150 @@
+# YAML support for the Go language
+
+Introduction
+------------
+
+The yaml package enables Go programs to comfortably encode and decode YAML
+values. It was developed within [Canonical](https://www.canonical.com) as
+part of the [juju](https://juju.ubuntu.com) project, and is based on a
+pure Go port of the well-known [libyaml](http://pyyaml.org/wiki/LibYAML)
+C library to parse and generate YAML data quickly and reliably.
+
+Compatibility
+-------------
+
+The yaml package supports most of YAML 1.2, but preserves some behavior
+from 1.1 for backwards compatibility.
+
+Specifically, as of v3 of the yaml package:
+
+ - YAML 1.1 bools (_yes/no, on/off_) are supported as long as they are being
+ decoded into a typed bool value. Otherwise they behave as a string. Booleans
+ in YAML 1.2 are _true/false_ only.
+ - Octals encode and decode as _0777_ per YAML 1.1, rather than _0o777_
+ as specified in YAML 1.2, because most parsers still use the old format.
+ Octals in the _0o777_ format are supported though, so new files work.
+ - Does not support base-60 floats. These are gone from YAML 1.2, and were
+ actually never supported by this package as it's clearly a poor choice.
+
+and offers backwards
+compatibility with YAML 1.1 in some cases.
+1.2, including support for
+anchors, tags, map merging, etc. Multi-document unmarshalling is not yet
+implemented, and base-60 floats from YAML 1.1 are purposefully not
+supported since they're a poor design and are gone in YAML 1.2.
+
+Installation and usage
+----------------------
+
+The import path for the package is *gopkg.in/yaml.v3*.
+
+To install it, run:
+
+ go get gopkg.in/yaml.v3
+
+API documentation
+-----------------
+
+If opened in a browser, the import path itself leads to the API documentation:
+
+ - [https://gopkg.in/yaml.v3](https://gopkg.in/yaml.v3)
+
+API stability
+-------------
+
+The package API for yaml v3 will remain stable as described in [gopkg.in](https://gopkg.in).
+
+
+License
+-------
+
+The yaml package is licensed under the MIT and Apache License 2.0 licenses.
+Please see the LICENSE file for details.
+
+
+Example
+-------
+
+```Go
+package main
+
+import (
+ "fmt"
+ "log"
+
+ "gopkg.in/yaml.v3"
+)
+
+var data = `
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+`
+
+// Note: struct fields must be public in order for unmarshal to
+// correctly populate the data.
+type T struct {
+ A string
+ B struct {
+ RenamedC int `yaml:"c"`
+ D []int `yaml:",flow"`
+ }
+}
+
+func main() {
+ t := T{}
+
+ err := yaml.Unmarshal([]byte(data), &t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t:\n%v\n\n", t)
+
+ d, err := yaml.Marshal(&t)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- t dump:\n%s\n\n", string(d))
+
+ m := make(map[interface{}]interface{})
+
+ err = yaml.Unmarshal([]byte(data), &m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m:\n%v\n\n", m)
+
+ d, err = yaml.Marshal(&m)
+ if err != nil {
+ log.Fatalf("error: %v", err)
+ }
+ fmt.Printf("--- m dump:\n%s\n\n", string(d))
+}
+```
+
+This example will generate the following output:
+
+```
+--- t:
+{Easy! {2 [3 4]}}
+
+--- t dump:
+a: Easy!
+b:
+ c: 2
+ d: [3, 4]
+
+
+--- m:
+map[a:Easy! b:map[c:2 d:[3 4]]]
+
+--- m dump:
+a: Easy!
+b:
+ c: 2
+ d:
+ - 3
+ - 4
+```
+
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/apic.go b/kyaml/internal/forked/github.com/go-yaml/yaml/apic.go
new file mode 100644
index 000000000..ae7d049f1
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/apic.go
@@ -0,0 +1,747 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "io"
+)
+
+func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
+ //fmt.Println("yaml_insert_token", "pos:", pos, "typ:", token.typ, "head:", parser.tokens_head, "len:", len(parser.tokens))
+
+ // Check if we can move the queue at the beginning of the buffer.
+ if parser.tokens_head > 0 && len(parser.tokens) == cap(parser.tokens) {
+ if parser.tokens_head != len(parser.tokens) {
+ copy(parser.tokens, parser.tokens[parser.tokens_head:])
+ }
+ parser.tokens = parser.tokens[:len(parser.tokens)-parser.tokens_head]
+ parser.tokens_head = 0
+ }
+ parser.tokens = append(parser.tokens, *token)
+ if pos < 0 {
+ return
+ }
+ copy(parser.tokens[parser.tokens_head+pos+1:], parser.tokens[parser.tokens_head+pos:])
+ parser.tokens[parser.tokens_head+pos] = *token
+}
+
+// Create a new parser object.
+func yaml_parser_initialize(parser *yaml_parser_t) bool {
+ *parser = yaml_parser_t{
+ raw_buffer: make([]byte, 0, input_raw_buffer_size),
+ buffer: make([]byte, 0, input_buffer_size),
+ }
+ return true
+}
+
+// Destroy a parser object.
+func yaml_parser_delete(parser *yaml_parser_t) {
+ *parser = yaml_parser_t{}
+}
+
+// String read handler.
+func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ if parser.input_pos == len(parser.input) {
+ return 0, io.EOF
+ }
+ n = copy(buffer, parser.input[parser.input_pos:])
+ parser.input_pos += n
+ return n, nil
+}
+
+// Reader read handler.
+func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
+ return parser.input_reader.Read(buffer)
+}
+
+// Set a string input.
+func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_string_read_handler
+ parser.input = input
+ parser.input_pos = 0
+}
+
+// Set a file input.
+func yaml_parser_set_input_reader(parser *yaml_parser_t, r io.Reader) {
+ if parser.read_handler != nil {
+ panic("must set the input source only once")
+ }
+ parser.read_handler = yaml_reader_read_handler
+ parser.input_reader = r
+}
+
+// Set the source encoding.
+func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
+ if parser.encoding != yaml_ANY_ENCODING {
+ panic("must set the encoding only once")
+ }
+ parser.encoding = encoding
+}
+
+// Create a new emitter object.
+func yaml_emitter_initialize(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{
+ buffer: make([]byte, output_buffer_size),
+ raw_buffer: make([]byte, 0, output_raw_buffer_size),
+ states: make([]yaml_emitter_state_t, 0, initial_stack_size),
+ events: make([]yaml_event_t, 0, initial_queue_size),
+ best_width: -1,
+ }
+}
+
+// Destroy an emitter object.
+func yaml_emitter_delete(emitter *yaml_emitter_t) {
+ *emitter = yaml_emitter_t{}
+}
+
+// String write handler.
+func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ *emitter.output_buffer = append(*emitter.output_buffer, buffer...)
+ return nil
+}
+
+// yaml_writer_write_handler uses emitter.output_writer to write the
+// emitted text.
+func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
+ _, err := emitter.output_writer.Write(buffer)
+ return err
+}
+
+// Set a string output.
+func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]byte) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_string_write_handler
+ emitter.output_buffer = output_buffer
+}
+
+// Set a file output.
+func yaml_emitter_set_output_writer(emitter *yaml_emitter_t, w io.Writer) {
+ if emitter.write_handler != nil {
+ panic("must set the output target only once")
+ }
+ emitter.write_handler = yaml_writer_write_handler
+ emitter.output_writer = w
+}
+
+// Set the output encoding.
+func yaml_emitter_set_encoding(emitter *yaml_emitter_t, encoding yaml_encoding_t) {
+ if emitter.encoding != yaml_ANY_ENCODING {
+ panic("must set the output encoding only once")
+ }
+ emitter.encoding = encoding
+}
+
+// Set the canonical output style.
+func yaml_emitter_set_canonical(emitter *yaml_emitter_t, canonical bool) {
+ emitter.canonical = canonical
+}
+
+// Set the indentation increment.
+func yaml_emitter_set_indent(emitter *yaml_emitter_t, indent int) {
+ if indent < 2 || indent > 9 {
+ indent = 2
+ }
+ emitter.best_indent = indent
+}
+
+// Set the preferred line width.
+func yaml_emitter_set_width(emitter *yaml_emitter_t, width int) {
+ if width < 0 {
+ width = -1
+ }
+ emitter.best_width = width
+}
+
+// Set if unescaped non-ASCII characters are allowed.
+func yaml_emitter_set_unicode(emitter *yaml_emitter_t, unicode bool) {
+ emitter.unicode = unicode
+}
+
+// Set the preferred line break character.
+func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
+ emitter.line_break = line_break
+}
+
+///*
+// * Destroy a token object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_token_delete(yaml_token_t *token)
+//{
+// assert(token); // Non-NULL token object expected.
+//
+// switch (token.type)
+// {
+// case YAML_TAG_DIRECTIVE_TOKEN:
+// yaml_free(token.data.tag_directive.handle);
+// yaml_free(token.data.tag_directive.prefix);
+// break;
+//
+// case YAML_ALIAS_TOKEN:
+// yaml_free(token.data.alias.value);
+// break;
+//
+// case YAML_ANCHOR_TOKEN:
+// yaml_free(token.data.anchor.value);
+// break;
+//
+// case YAML_TAG_TOKEN:
+// yaml_free(token.data.tag.handle);
+// yaml_free(token.data.tag.suffix);
+// break;
+//
+// case YAML_SCALAR_TOKEN:
+// yaml_free(token.data.scalar.value);
+// break;
+//
+// default:
+// break;
+// }
+//
+// memset(token, 0, sizeof(yaml_token_t));
+//}
+//
+///*
+// * Check if a string is a valid UTF-8 sequence.
+// *
+// * Check 'reader.c' for more details on UTF-8 encoding.
+// */
+//
+//static int
+//yaml_check_utf8(yaml_char_t *start, size_t length)
+//{
+// yaml_char_t *end = start+length;
+// yaml_char_t *pointer = start;
+//
+// while (pointer < end) {
+// unsigned char octet;
+// unsigned int width;
+// unsigned int value;
+// size_t k;
+//
+// octet = pointer[0];
+// width = (octet & 0x80) == 0x00 ? 1 :
+// (octet & 0xE0) == 0xC0 ? 2 :
+// (octet & 0xF0) == 0xE0 ? 3 :
+// (octet & 0xF8) == 0xF0 ? 4 : 0;
+// value = (octet & 0x80) == 0x00 ? octet & 0x7F :
+// (octet & 0xE0) == 0xC0 ? octet & 0x1F :
+// (octet & 0xF0) == 0xE0 ? octet & 0x0F :
+// (octet & 0xF8) == 0xF0 ? octet & 0x07 : 0;
+// if (!width) return 0;
+// if (pointer+width > end) return 0;
+// for (k = 1; k < width; k ++) {
+// octet = pointer[k];
+// if ((octet & 0xC0) != 0x80) return 0;
+// value = (value << 6) + (octet & 0x3F);
+// }
+// if (!((width == 1) ||
+// (width == 2 && value >= 0x80) ||
+// (width == 3 && value >= 0x800) ||
+// (width == 4 && value >= 0x10000))) return 0;
+//
+// pointer += width;
+// }
+//
+// return 1;
+//}
+//
+
+// Create STREAM-START.
+func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_START_EVENT,
+ encoding: encoding,
+ }
+}
+
+// Create STREAM-END.
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_STREAM_END_EVENT,
+ }
+}
+
+// Create DOCUMENT-START.
+func yaml_document_start_event_initialize(
+ event *yaml_event_t,
+ version_directive *yaml_version_directive_t,
+ tag_directives []yaml_tag_directive_t,
+ implicit bool,
+) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_START_EVENT,
+ version_directive: version_directive,
+ tag_directives: tag_directives,
+ implicit: implicit,
+ }
+}
+
+// Create DOCUMENT-END.
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
+ *event = yaml_event_t{
+ typ: yaml_DOCUMENT_END_EVENT,
+ implicit: implicit,
+ }
+}
+
+// Create ALIAS.
+func yaml_alias_event_initialize(event *yaml_event_t, anchor []byte) bool {
+ *event = yaml_event_t{
+ typ: yaml_ALIAS_EVENT,
+ anchor: anchor,
+ }
+ return true
+}
+
+// Create SCALAR.
+func yaml_scalar_event_initialize(event *yaml_event_t, anchor, tag, value []byte, plain_implicit, quoted_implicit bool, style yaml_scalar_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SCALAR_EVENT,
+ anchor: anchor,
+ tag: tag,
+ value: value,
+ implicit: plain_implicit,
+ quoted_implicit: quoted_implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-START.
+func yaml_sequence_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_sequence_style_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+ return true
+}
+
+// Create SEQUENCE-END.
+func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
+ *event = yaml_event_t{
+ typ: yaml_SEQUENCE_END_EVENT,
+ }
+ return true
+}
+
+// Create MAPPING-START.
+func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_START_EVENT,
+ anchor: anchor,
+ tag: tag,
+ implicit: implicit,
+ style: yaml_style_t(style),
+ }
+}
+
+// Create MAPPING-END.
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
+ *event = yaml_event_t{
+ typ: yaml_MAPPING_END_EVENT,
+ }
+}
+
+// Destroy an event object.
+func yaml_event_delete(event *yaml_event_t) {
+ *event = yaml_event_t{}
+}
+
+///*
+// * Create a document object.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_initialize(document *yaml_document_t,
+// version_directive *yaml_version_directive_t,
+// tag_directives_start *yaml_tag_directive_t,
+// tag_directives_end *yaml_tag_directive_t,
+// start_implicit int, end_implicit int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// struct {
+// start *yaml_node_t
+// end *yaml_node_t
+// top *yaml_node_t
+// } nodes = { NULL, NULL, NULL }
+// version_directive_copy *yaml_version_directive_t = NULL
+// struct {
+// start *yaml_tag_directive_t
+// end *yaml_tag_directive_t
+// top *yaml_tag_directive_t
+// } tag_directives_copy = { NULL, NULL, NULL }
+// value yaml_tag_directive_t = { NULL, NULL }
+// mark yaml_mark_t = { 0, 0, 0 }
+//
+// assert(document) // Non-NULL document object is expected.
+// assert((tag_directives_start && tag_directives_end) ||
+// (tag_directives_start == tag_directives_end))
+// // Valid tag directives are expected.
+//
+// if (!STACK_INIT(&context, nodes, INITIAL_STACK_SIZE)) goto error
+//
+// if (version_directive) {
+// version_directive_copy = yaml_malloc(sizeof(yaml_version_directive_t))
+// if (!version_directive_copy) goto error
+// version_directive_copy.major = version_directive.major
+// version_directive_copy.minor = version_directive.minor
+// }
+//
+// if (tag_directives_start != tag_directives_end) {
+// tag_directive *yaml_tag_directive_t
+// if (!STACK_INIT(&context, tag_directives_copy, INITIAL_STACK_SIZE))
+// goto error
+// for (tag_directive = tag_directives_start
+// tag_directive != tag_directives_end; tag_directive ++) {
+// assert(tag_directive.handle)
+// assert(tag_directive.prefix)
+// if (!yaml_check_utf8(tag_directive.handle,
+// strlen((char *)tag_directive.handle)))
+// goto error
+// if (!yaml_check_utf8(tag_directive.prefix,
+// strlen((char *)tag_directive.prefix)))
+// goto error
+// value.handle = yaml_strdup(tag_directive.handle)
+// value.prefix = yaml_strdup(tag_directive.prefix)
+// if (!value.handle || !value.prefix) goto error
+// if (!PUSH(&context, tag_directives_copy, value))
+// goto error
+// value.handle = NULL
+// value.prefix = NULL
+// }
+// }
+//
+// DOCUMENT_INIT(*document, nodes.start, nodes.end, version_directive_copy,
+// tag_directives_copy.start, tag_directives_copy.top,
+// start_implicit, end_implicit, mark, mark)
+//
+// return 1
+//
+//error:
+// STACK_DEL(&context, nodes)
+// yaml_free(version_directive_copy)
+// while (!STACK_EMPTY(&context, tag_directives_copy)) {
+// value yaml_tag_directive_t = POP(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+// }
+// STACK_DEL(&context, tag_directives_copy)
+// yaml_free(value.handle)
+// yaml_free(value.prefix)
+//
+// return 0
+//}
+//
+///*
+// * Destroy a document object.
+// */
+//
+//YAML_DECLARE(void)
+//yaml_document_delete(document *yaml_document_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// tag_directive *yaml_tag_directive_t
+//
+// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// while (!STACK_EMPTY(&context, document.nodes)) {
+// node yaml_node_t = POP(&context, document.nodes)
+// yaml_free(node.tag)
+// switch (node.type) {
+// case YAML_SCALAR_NODE:
+// yaml_free(node.data.scalar.value)
+// break
+// case YAML_SEQUENCE_NODE:
+// STACK_DEL(&context, node.data.sequence.items)
+// break
+// case YAML_MAPPING_NODE:
+// STACK_DEL(&context, node.data.mapping.pairs)
+// break
+// default:
+// assert(0) // Should not happen.
+// }
+// }
+// STACK_DEL(&context, document.nodes)
+//
+// yaml_free(document.version_directive)
+// for (tag_directive = document.tag_directives.start
+// tag_directive != document.tag_directives.end
+// tag_directive++) {
+// yaml_free(tag_directive.handle)
+// yaml_free(tag_directive.prefix)
+// }
+// yaml_free(document.tag_directives.start)
+//
+// memset(document, 0, sizeof(yaml_document_t))
+//}
+//
+///**
+// * Get a document node.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_node(document *yaml_document_t, index int)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (index > 0 && document.nodes.start + index <= document.nodes.top) {
+// return document.nodes.start + index - 1
+// }
+// return NULL
+//}
+//
+///**
+// * Get the root object.
+// */
+//
+//YAML_DECLARE(yaml_node_t *)
+//yaml_document_get_root_node(document *yaml_document_t)
+//{
+// assert(document) // Non-NULL document object is expected.
+//
+// if (document.nodes.top != document.nodes.start) {
+// return document.nodes.start
+// }
+// return NULL
+//}
+//
+///*
+// * Add a scalar node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_scalar(document *yaml_document_t,
+// tag *yaml_char_t, value *yaml_char_t, length int,
+// style yaml_scalar_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// value_copy *yaml_char_t = NULL
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+// assert(value) // Non-NULL value is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SCALAR_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (length < 0) {
+// length = strlen((char *)value)
+// }
+//
+// if (!yaml_check_utf8(value, length)) goto error
+// value_copy = yaml_malloc(length+1)
+// if (!value_copy) goto error
+// memcpy(value_copy, value, length)
+// value_copy[length] = '\0'
+//
+// SCALAR_NODE_INIT(node, tag_copy, value_copy, length, style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// yaml_free(tag_copy)
+// yaml_free(value_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a sequence node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_sequence(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_sequence_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_item_t
+// end *yaml_node_item_t
+// top *yaml_node_item_t
+// } items = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_SEQUENCE_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, items, INITIAL_STACK_SIZE)) goto error
+//
+// SEQUENCE_NODE_INIT(node, tag_copy, items.start, items.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, items)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Add a mapping node to a document.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_add_mapping(document *yaml_document_t,
+// tag *yaml_char_t, style yaml_mapping_style_t)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+// mark yaml_mark_t = { 0, 0, 0 }
+// tag_copy *yaml_char_t = NULL
+// struct {
+// start *yaml_node_pair_t
+// end *yaml_node_pair_t
+// top *yaml_node_pair_t
+// } pairs = { NULL, NULL, NULL }
+// node yaml_node_t
+//
+// assert(document) // Non-NULL document object is expected.
+//
+// if (!tag) {
+// tag = (yaml_char_t *)YAML_DEFAULT_MAPPING_TAG
+// }
+//
+// if (!yaml_check_utf8(tag, strlen((char *)tag))) goto error
+// tag_copy = yaml_strdup(tag)
+// if (!tag_copy) goto error
+//
+// if (!STACK_INIT(&context, pairs, INITIAL_STACK_SIZE)) goto error
+//
+// MAPPING_NODE_INIT(node, tag_copy, pairs.start, pairs.end,
+// style, mark, mark)
+// if (!PUSH(&context, document.nodes, node)) goto error
+//
+// return document.nodes.top - document.nodes.start
+//
+//error:
+// STACK_DEL(&context, pairs)
+// yaml_free(tag_copy)
+//
+// return 0
+//}
+//
+///*
+// * Append an item to a sequence node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_sequence_item(document *yaml_document_t,
+// sequence int, item int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// assert(document) // Non-NULL document is required.
+// assert(sequence > 0
+// && document.nodes.start + sequence <= document.nodes.top)
+// // Valid sequence id is required.
+// assert(document.nodes.start[sequence-1].type == YAML_SEQUENCE_NODE)
+// // A sequence node is required.
+// assert(item > 0 && document.nodes.start + item <= document.nodes.top)
+// // Valid item id is required.
+//
+// if (!PUSH(&context,
+// document.nodes.start[sequence-1].data.sequence.items, item))
+// return 0
+//
+// return 1
+//}
+//
+///*
+// * Append a pair of a key and a value to a mapping node.
+// */
+//
+//YAML_DECLARE(int)
+//yaml_document_append_mapping_pair(document *yaml_document_t,
+// mapping int, key int, value int)
+//{
+// struct {
+// error yaml_error_type_t
+// } context
+//
+// pair yaml_node_pair_t
+//
+// assert(document) // Non-NULL document is required.
+// assert(mapping > 0
+// && document.nodes.start + mapping <= document.nodes.top)
+// // Valid mapping id is required.
+// assert(document.nodes.start[mapping-1].type == YAML_MAPPING_NODE)
+// // A mapping node is required.
+// assert(key > 0 && document.nodes.start + key <= document.nodes.top)
+// // Valid key id is required.
+// assert(value > 0 && document.nodes.start + value <= document.nodes.top)
+// // Valid value id is required.
+//
+// pair.key = key
+// pair.value = value
+//
+// if (!PUSH(&context,
+// document.nodes.start[mapping-1].data.mapping.pairs, pair))
+// return 0
+//
+// return 1
+//}
+//
+//
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/decode.go b/kyaml/internal/forked/github.com/go-yaml/yaml/decode.go
new file mode 100644
index 000000000..df36e3a30
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/decode.go
@@ -0,0 +1,950 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strconv"
+ "time"
+)
+
+// ----------------------------------------------------------------------------
+// Parser, produces a node tree out of a libyaml event stream.
+
+type parser struct {
+ parser yaml_parser_t
+ event yaml_event_t
+ doc *Node
+ anchors map[string]*Node
+ doneInit bool
+ textless bool
+}
+
+func newParser(b []byte) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ if len(b) == 0 {
+ b = []byte{'\n'}
+ }
+ yaml_parser_set_input_string(&p.parser, b)
+ return &p
+}
+
+func newParserFromReader(r io.Reader) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
+ }
+ yaml_parser_set_input_reader(&p.parser, r)
+ return &p
+}
+
+func (p *parser) init() {
+ if p.doneInit {
+ return
+ }
+ p.anchors = make(map[string]*Node)
+ p.expect(yaml_STREAM_START_EVENT)
+ p.doneInit = true
+}
+
+func (p *parser) destroy() {
+ if p.event.typ != yaml_NO_EVENT {
+ yaml_event_delete(&p.event)
+ }
+ yaml_parser_delete(&p.parser)
+}
+
+// expect consumes an event from the event stream and
+// checks that it's of the expected type.
+func (p *parser) expect(e yaml_event_type_t) {
+ if p.event.typ == yaml_NO_EVENT {
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ }
+ if p.event.typ == yaml_STREAM_END_EVENT {
+ failf("attempted to go past the end of stream; corrupted value?")
+ }
+ if p.event.typ != e {
+ p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
+ p.fail()
+ }
+ yaml_event_delete(&p.event)
+ p.event.typ = yaml_NO_EVENT
+}
+
+// peek peeks at the next event in the event stream,
+// puts the results into p.event and returns the event type.
+func (p *parser) peek() yaml_event_type_t {
+ if p.event.typ != yaml_NO_EVENT {
+ return p.event.typ
+ }
+ if !yaml_parser_parse(&p.parser, &p.event) {
+ p.fail()
+ }
+ return p.event.typ
+}
+
+func (p *parser) fail() {
+ var where string
+ var line int
+ if p.parser.context_mark.line != 0 {
+ line = p.parser.context_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ } else if p.parser.problem_mark.line != 0 {
+ line = p.parser.problem_mark.line
+ // Scanner errors don't iterate line before returning error
+ if p.parser.error == yaml_SCANNER_ERROR {
+ line++
+ }
+ }
+ if line != 0 {
+ where = "line " + strconv.Itoa(line) + ": "
+ }
+ var msg string
+ if len(p.parser.problem) > 0 {
+ msg = p.parser.problem
+ } else {
+ msg = "unknown problem parsing YAML content"
+ }
+ failf("%s%s", where, msg)
+}
+
+func (p *parser) anchor(n *Node, anchor []byte) {
+ if anchor != nil {
+ n.Anchor = string(anchor)
+ p.anchors[n.Anchor] = n
+ }
+}
+
+func (p *parser) parse() *Node {
+ p.init()
+ switch p.peek() {
+ case yaml_SCALAR_EVENT:
+ return p.scalar()
+ case yaml_ALIAS_EVENT:
+ return p.alias()
+ case yaml_MAPPING_START_EVENT:
+ return p.mapping()
+ case yaml_SEQUENCE_START_EVENT:
+ return p.sequence()
+ case yaml_DOCUMENT_START_EVENT:
+ return p.document()
+ case yaml_STREAM_END_EVENT:
+ // Happens when attempting to decode an empty buffer.
+ return nil
+ case yaml_TAIL_COMMENT_EVENT:
+ panic("internal error: unexpected tail comment event (please report)")
+ default:
+ panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String())
+ }
+}
+
+func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node {
+ var style Style
+ if tag != "" && tag != "!" {
+ tag = shortTag(tag)
+ style = TaggedStyle
+ } else if defaultTag != "" {
+ tag = defaultTag
+ } else if kind == ScalarNode {
+ tag, _ = resolve("", value)
+ }
+ n := &Node{
+ Kind: kind,
+ Tag: tag,
+ Value: value,
+ Style: style,
+ }
+ if !p.textless {
+ n.Line = p.event.start_mark.line + 1
+ n.Column = p.event.start_mark.column + 1
+ n.HeadComment = string(p.event.head_comment)
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ }
+ return n
+}
+
+func (p *parser) parseChild(parent *Node) *Node {
+ child := p.parse()
+ parent.Content = append(parent.Content, child)
+ return child
+}
+
+func (p *parser) document() *Node {
+ n := p.node(DocumentNode, "", "", "")
+ p.doc = n
+ p.expect(yaml_DOCUMENT_START_EVENT)
+ p.parseChild(n)
+ if p.peek() == yaml_DOCUMENT_END_EVENT {
+ n.FootComment = string(p.event.foot_comment)
+ }
+ p.expect(yaml_DOCUMENT_END_EVENT)
+ return n
+}
+
+func (p *parser) alias() *Node {
+ n := p.node(AliasNode, "", "", string(p.event.anchor))
+ n.Alias = p.anchors[n.Value]
+ if n.Alias == nil {
+ failf("unknown anchor '%s' referenced", n.Value)
+ }
+ p.expect(yaml_ALIAS_EVENT)
+ return n
+}
+
+func (p *parser) scalar() *Node {
+ var parsedStyle = p.event.scalar_style()
+ var nodeStyle Style
+ switch {
+ case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = DoubleQuotedStyle
+ case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0:
+ nodeStyle = SingleQuotedStyle
+ case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0:
+ nodeStyle = LiteralStyle
+ case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0:
+ nodeStyle = FoldedStyle
+ }
+ var nodeValue = string(p.event.value)
+ var nodeTag = string(p.event.tag)
+ var defaultTag string
+ if nodeStyle == 0 {
+ if nodeValue == "<<" {
+ defaultTag = mergeTag
+ }
+ } else {
+ defaultTag = strTag
+ }
+ n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue)
+ n.Style |= nodeStyle
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SCALAR_EVENT)
+ return n
+}
+
+func (p *parser) sequence() *Node {
+ n := p.node(SequenceNode, seqTag, string(p.event.tag), "")
+ if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 {
+ n.Style |= FlowStyle
+ }
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_SEQUENCE_START_EVENT)
+ for p.peek() != yaml_SEQUENCE_END_EVENT {
+ p.parseChild(n)
+ }
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ p.expect(yaml_SEQUENCE_END_EVENT)
+ return n
+}
+
+func (p *parser) mapping() *Node {
+ n := p.node(MappingNode, mapTag, string(p.event.tag), "")
+ block := true
+ if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 {
+ block = false
+ n.Style |= FlowStyle
+ }
+ p.anchor(n, p.event.anchor)
+ p.expect(yaml_MAPPING_START_EVENT)
+ for p.peek() != yaml_MAPPING_END_EVENT {
+ k := p.parseChild(n)
+ if block && k.FootComment != "" {
+ // Must be a foot comment for the prior value when being dedented.
+ if len(n.Content) > 2 {
+ n.Content[len(n.Content)-3].FootComment = k.FootComment
+ k.FootComment = ""
+ }
+ }
+ v := p.parseChild(n)
+ if k.FootComment == "" && v.FootComment != "" {
+ k.FootComment = v.FootComment
+ v.FootComment = ""
+ }
+ if p.peek() == yaml_TAIL_COMMENT_EVENT {
+ if k.FootComment == "" {
+ k.FootComment = string(p.event.foot_comment)
+ }
+ p.expect(yaml_TAIL_COMMENT_EVENT)
+ }
+ }
+ n.LineComment = string(p.event.line_comment)
+ n.FootComment = string(p.event.foot_comment)
+ if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 {
+ n.Content[len(n.Content)-2].FootComment = n.FootComment
+ n.FootComment = ""
+ }
+ p.expect(yaml_MAPPING_END_EVENT)
+ return n
+}
+
+// ----------------------------------------------------------------------------
+// Decoder, unmarshals a node into a provided value.
+
+type decoder struct {
+ doc *Node
+ aliases map[*Node]bool
+ terrors []string
+
+ stringMapType reflect.Type
+ generalMapType reflect.Type
+
+ knownFields bool
+ uniqueKeys bool
+ decodeCount int
+ aliasCount int
+ aliasDepth int
+}
+
+var (
+ nodeType = reflect.TypeOf(Node{})
+ durationType = reflect.TypeOf(time.Duration(0))
+ stringMapType = reflect.TypeOf(map[string]interface{}{})
+ generalMapType = reflect.TypeOf(map[interface{}]interface{}{})
+ ifaceType = generalMapType.Elem()
+ timeType = reflect.TypeOf(time.Time{})
+ ptrTimeType = reflect.TypeOf(&time.Time{})
+)
+
+func newDecoder() *decoder {
+ d := &decoder{
+ stringMapType: stringMapType,
+ generalMapType: generalMapType,
+ uniqueKeys: true,
+ }
+ d.aliases = make(map[*Node]bool)
+ return d
+}
+
+func (d *decoder) terror(n *Node, tag string, out reflect.Value) {
+ if n.Tag != "" {
+ tag = n.Tag
+ }
+ value := n.Value
+ if tag != seqTag && tag != mapTag {
+ if len(value) > 10 {
+ value = " `" + value[:7] + "...`"
+ } else {
+ value = " `" + value + "`"
+ }
+ }
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type()))
+}
+
+func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) {
+ err := u.UnmarshalYAML(n)
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) {
+ terrlen := len(d.terrors)
+ err := u.UnmarshalYAML(func(v interface{}) (err error) {
+ defer handleErr(&err)
+ d.unmarshal(n, reflect.ValueOf(v))
+ if len(d.terrors) > terrlen {
+ issues := d.terrors[terrlen:]
+ d.terrors = d.terrors[:terrlen]
+ return &TypeError{issues}
+ }
+ return nil
+ })
+ if e, ok := err.(*TypeError); ok {
+ d.terrors = append(d.terrors, e.Errors...)
+ return false
+ }
+ if err != nil {
+ fail(err)
+ }
+ return true
+}
+
+// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
+// if a value is found to implement it.
+// It returns the initialized and dereferenced out value, whether
+// unmarshalling was already done by UnmarshalYAML, and if so whether
+// its types unmarshalled appropriately.
+//
+// If n holds a null value, prepare returns before doing anything.
+func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
+ if n.ShortTag() == nullTag {
+ return out, false, false
+ }
+ again := true
+ for again {
+ again = false
+ if out.Kind() == reflect.Ptr {
+ if out.IsNil() {
+ out.Set(reflect.New(out.Type().Elem()))
+ }
+ out = out.Elem()
+ again = true
+ }
+ if out.CanAddr() {
+ outi := out.Addr().Interface()
+ if u, ok := outi.(Unmarshaler); ok {
+ good = d.callUnmarshaler(n, u)
+ return out, true, good
+ }
+ if u, ok := outi.(obsoleteUnmarshaler); ok {
+ good = d.callObsoleteUnmarshaler(n, u)
+ return out, true, good
+ }
+ }
+ }
+ return out, false, false
+}
+
+func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) {
+ if n.ShortTag() == nullTag {
+ return reflect.Value{}
+ }
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+const (
+ // 400,000 decode operations is ~500kb of dense object declarations, or
+ // ~5kb of dense object declarations with 10000% alias expansion
+ alias_ratio_range_low = 400000
+
+ // 4,000,000 decode operations is ~5MB of dense object declarations, or
+ // ~4.5MB of dense object declarations with 10% alias expansion
+ alias_ratio_range_high = 4000000
+
+ // alias_ratio_range is the range over which we scale allowed alias ratios
+ alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
+)
+
+func allowedAliasRatio(decodeCount int) float64 {
+ switch {
+ case decodeCount <= alias_ratio_range_low:
+ // allow 99% to come from alias expansion for small-to-medium documents
+ return 0.99
+ case decodeCount >= alias_ratio_range_high:
+ // allow 10% to come from alias expansion for very large documents
+ return 0.10
+ default:
+ // scale smoothly from 99% down to 10% over the range.
+ // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
+ // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
+ return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
+ }
+}
+
+func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) {
+ d.decodeCount++
+ if d.aliasDepth > 0 {
+ d.aliasCount++
+ }
+ if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
+ failf("document contains excessive aliasing")
+ }
+ if out.Type() == nodeType {
+ out.Set(reflect.ValueOf(n).Elem())
+ return true
+ }
+ switch n.Kind {
+ case DocumentNode:
+ return d.document(n, out)
+ case AliasNode:
+ return d.alias(n, out)
+ }
+ out, unmarshaled, good := d.prepare(n, out)
+ if unmarshaled {
+ return good
+ }
+ switch n.Kind {
+ case ScalarNode:
+ good = d.scalar(n, out)
+ case MappingNode:
+ good = d.mapping(n, out)
+ case SequenceNode:
+ good = d.sequence(n, out)
+ case 0:
+ if n.IsZero() {
+ return d.null(out)
+ }
+ fallthrough
+ default:
+ failf("cannot decode node with unknown kind %d", n.Kind)
+ }
+ return good
+}
+
+func (d *decoder) document(n *Node, out reflect.Value) (good bool) {
+ if len(n.Content) == 1 {
+ d.doc = n
+ d.unmarshal(n.Content[0], out)
+ return true
+ }
+ return false
+}
+
+func (d *decoder) alias(n *Node, out reflect.Value) (good bool) {
+ if d.aliases[n] {
+ // TODO this could actually be allowed in some circumstances.
+ failf("anchor '%s' value contains itself", n.Value)
+ }
+ d.aliases[n] = true
+ d.aliasDepth++
+ good = d.unmarshal(n.Alias, out)
+ d.aliasDepth--
+ delete(d.aliases, n)
+ return good
+}
+
+var zeroValue reflect.Value
+
+func resetMap(out reflect.Value) {
+ for _, k := range out.MapKeys() {
+ out.SetMapIndex(k, zeroValue)
+ }
+}
+
+func (d *decoder) null(out reflect.Value) bool {
+ if out.CanAddr() {
+ switch out.Kind() {
+ case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice:
+ out.Set(reflect.Zero(out.Type()))
+ return true
+ }
+ }
+ return false
+}
+
+func (d *decoder) scalar(n *Node, out reflect.Value) bool {
+ var tag string
+ var resolved interface{}
+ if n.indicatedString() {
+ tag = strTag
+ resolved = n.Value
+ } else {
+ tag, resolved = resolve(n.Tag, n.Value)
+ if tag == binaryTag {
+ data, err := base64.StdEncoding.DecodeString(resolved.(string))
+ if err != nil {
+ failf("!!binary value contains invalid base64 data")
+ }
+ resolved = string(data)
+ }
+ }
+ if resolved == nil {
+ return d.null(out)
+ }
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ // We've resolved to exactly the type we want, so use that.
+ out.Set(resolvedv)
+ return true
+ }
+ // Perhaps we can use the value as a TextUnmarshaler to
+ // set its value.
+ if out.CanAddr() {
+ u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
+ if ok {
+ var text []byte
+ if tag == binaryTag {
+ text = []byte(resolved.(string))
+ } else {
+ // We let any value be unmarshaled into TextUnmarshaler.
+ // That might be more lax than we'd like, but the
+ // TextUnmarshaler itself should bowl out any dubious values.
+ text = []byte(n.Value)
+ }
+ err := u.UnmarshalText(text)
+ if err != nil {
+ fail(err)
+ }
+ return true
+ }
+ }
+ switch out.Kind() {
+ case reflect.String:
+ if tag == binaryTag {
+ out.SetString(resolved.(string))
+ return true
+ }
+ out.SetString(n.Value)
+ return true
+ case reflect.Interface:
+ out.Set(reflect.ValueOf(resolved))
+ return true
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ // This used to work in v2, but it's very unfriendly.
+ isDuration := out.Type() == durationType
+
+ switch resolved := resolved.(type) {
+ case int:
+ if !isDuration && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case int64:
+ if !isDuration && !out.OverflowInt(resolved) {
+ out.SetInt(resolved)
+ return true
+ }
+ case uint64:
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case float64:
+ if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
+ out.SetInt(int64(resolved))
+ return true
+ }
+ case string:
+ if out.Type() == durationType {
+ d, err := time.ParseDuration(resolved)
+ if err == nil {
+ out.SetInt(int64(d))
+ return true
+ }
+ }
+ }
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ switch resolved := resolved.(type) {
+ case int:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case int64:
+ if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case uint64:
+ if !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ case float64:
+ if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
+ out.SetUint(uint64(resolved))
+ return true
+ }
+ }
+ case reflect.Bool:
+ switch resolved := resolved.(type) {
+ case bool:
+ out.SetBool(resolved)
+ return true
+ case string:
+ // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html).
+ // It only works if explicitly attempting to unmarshal into a typed bool value.
+ switch resolved {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON":
+ out.SetBool(true)
+ return true
+ case "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ out.SetBool(false)
+ return true
+ }
+ }
+ case reflect.Float32, reflect.Float64:
+ switch resolved := resolved.(type) {
+ case int:
+ out.SetFloat(float64(resolved))
+ return true
+ case int64:
+ out.SetFloat(float64(resolved))
+ return true
+ case uint64:
+ out.SetFloat(float64(resolved))
+ return true
+ case float64:
+ out.SetFloat(resolved)
+ return true
+ }
+ case reflect.Struct:
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ out.Set(resolvedv)
+ return true
+ }
+ case reflect.Ptr:
+ panic("yaml internal error: please report the issue")
+ }
+ d.terror(n, tag, out)
+ return false
+}
+
+func settableValueOf(i interface{}) reflect.Value {
+ v := reflect.ValueOf(i)
+ sv := reflect.New(v.Type()).Elem()
+ sv.Set(v)
+ return sv
+}
+
+func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+
+ var iface reflect.Value
+ switch out.Kind() {
+ case reflect.Slice:
+ out.Set(reflect.MakeSlice(out.Type(), l, l))
+ case reflect.Array:
+ if l != out.Len() {
+ failf("invalid array: want %d elements but got %d", out.Len(), l)
+ }
+ case reflect.Interface:
+ // No type hints. Will have to use a generic sequence.
+ iface = out
+ out = settableValueOf(make([]interface{}, l))
+ default:
+ d.terror(n, seqTag, out)
+ return false
+ }
+ et := out.Type().Elem()
+
+ j := 0
+ for i := 0; i < l; i++ {
+ e := reflect.New(et).Elem()
+ if ok := d.unmarshal(n.Content[i], e); ok {
+ out.Index(j).Set(e)
+ j++
+ }
+ }
+ if out.Kind() != reflect.Array {
+ out.Set(out.Slice(0, j))
+ }
+ if iface.IsValid() {
+ iface.Set(out)
+ }
+ return true
+}
+
+func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) {
+ l := len(n.Content)
+ if d.uniqueKeys {
+ nerrs := len(d.terrors)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ for j := i + 2; j < l; j += 2 {
+ nj := n.Content[j]
+ if ni.Kind == nj.Kind && ni.Value == nj.Value {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line))
+ }
+ }
+ }
+ if len(d.terrors) > nerrs {
+ return false
+ }
+ }
+ switch out.Kind() {
+ case reflect.Struct:
+ return d.mappingStruct(n, out)
+ case reflect.Map:
+ // okay
+ case reflect.Interface:
+ iface := out
+ if isStringMap(n) {
+ out = reflect.MakeMap(d.stringMapType)
+ } else {
+ out = reflect.MakeMap(d.generalMapType)
+ }
+ iface.Set(out)
+ default:
+ d.terror(n, mapTag, out)
+ return false
+ }
+
+ outt := out.Type()
+ kt := outt.Key()
+ et := outt.Elem()
+
+ stringMapType := d.stringMapType
+ generalMapType := d.generalMapType
+ if outt.Elem() == ifaceType {
+ if outt.Key().Kind() == reflect.String {
+ d.stringMapType = outt
+ } else if outt.Key() == ifaceType {
+ d.generalMapType = outt
+ }
+ }
+
+ mapIsNew := false
+ if out.IsNil() {
+ out.Set(reflect.MakeMap(outt))
+ mapIsNew = true
+ }
+ for i := 0; i < l; i += 2 {
+ if isMerge(n.Content[i]) {
+ d.merge(n.Content[i+1], out)
+ continue
+ }
+ k := reflect.New(kt).Elem()
+ if d.unmarshal(n.Content[i], k) {
+ kkind := k.Kind()
+ if kkind == reflect.Interface {
+ kkind = k.Elem().Kind()
+ }
+ if kkind == reflect.Map || kkind == reflect.Slice {
+ failf("invalid map key: %#v", k.Interface())
+ }
+ e := reflect.New(et).Elem()
+ if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) {
+ out.SetMapIndex(k, e)
+ }
+ }
+ }
+ d.stringMapType = stringMapType
+ d.generalMapType = generalMapType
+ return true
+}
+
+func isStringMap(n *Node) bool {
+ if n.Kind != MappingNode {
+ return false
+ }
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ if n.Content[i].ShortTag() != strTag {
+ return false
+ }
+ }
+ return true
+}
+
+func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) {
+ sinfo, err := getStructInfo(out.Type())
+ if err != nil {
+ panic(err)
+ }
+
+ var inlineMap reflect.Value
+ var elemType reflect.Type
+ if sinfo.InlineMap != -1 {
+ inlineMap = out.Field(sinfo.InlineMap)
+ inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
+ elemType = inlineMap.Type().Elem()
+ }
+
+ for _, index := range sinfo.InlineUnmarshalers {
+ field := d.fieldByIndex(n, out, index)
+ d.prepare(n, field)
+ }
+
+ var doneFields []bool
+ if d.uniqueKeys {
+ doneFields = make([]bool, len(sinfo.FieldsList))
+ }
+ name := settableValueOf("")
+ l := len(n.Content)
+ for i := 0; i < l; i += 2 {
+ ni := n.Content[i]
+ if isMerge(ni) {
+ d.merge(n.Content[i+1], out)
+ continue
+ }
+ if !d.unmarshal(ni, name) {
+ continue
+ }
+ if info, ok := sinfo.FieldsMap[name.String()]; ok {
+ if d.uniqueKeys {
+ if doneFields[info.Id] {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type()))
+ continue
+ }
+ doneFields[info.Id] = true
+ }
+ var field reflect.Value
+ if info.Inline == nil {
+ field = out.Field(info.Num)
+ } else {
+ field = d.fieldByIndex(n, out, info.Inline)
+ }
+ d.unmarshal(n.Content[i+1], field)
+ } else if sinfo.InlineMap != -1 {
+ if inlineMap.IsNil() {
+ inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
+ }
+ value := reflect.New(elemType).Elem()
+ d.unmarshal(n.Content[i+1], value)
+ inlineMap.SetMapIndex(name, value)
+ } else if d.knownFields {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type()))
+ }
+ }
+ return true
+}
+
+func failWantMap() {
+ failf("map merge requires map or sequence of maps as the value")
+}
+
+func (d *decoder) merge(n *Node, out reflect.Value) {
+ switch n.Kind {
+ case MappingNode:
+ d.unmarshal(n, out)
+ case AliasNode:
+ if n.Alias != nil && n.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ d.unmarshal(n, out)
+ case SequenceNode:
+ // Step backwards as earlier nodes take precedence.
+ for i := len(n.Content) - 1; i >= 0; i-- {
+ ni := n.Content[i]
+ if ni.Kind == AliasNode {
+ if ni.Alias != nil && ni.Alias.Kind != MappingNode {
+ failWantMap()
+ }
+ } else if ni.Kind != MappingNode {
+ failWantMap()
+ }
+ d.unmarshal(ni, out)
+ }
+ default:
+ failWantMap()
+ }
+}
+
+func isMerge(n *Node) bool {
+ return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag)
+}
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/decode_test.go b/kyaml/internal/forked/github.com/go-yaml/yaml/decode_test.go
new file mode 100644
index 000000000..7b34fade2
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/decode_test.go
@@ -0,0 +1,1674 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml_test
+
+import (
+ "bytes"
+ "errors"
+ "fmt"
+ "io"
+ "math"
+ "reflect"
+ "strings"
+ "time"
+
+ . "gopkg.in/check.v1"
+ "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
+)
+
+var unmarshalIntTest = 123
+
+var unmarshalTests = []struct {
+ data string
+ value interface{}
+}{
+ {
+ "",
+ (*struct{})(nil),
+ },
+ {
+ "{}", &struct{}{},
+ }, {
+ "v: hi",
+ map[string]string{"v": "hi"},
+ }, {
+ "v: hi", map[string]interface{}{"v": "hi"},
+ }, {
+ "v: true",
+ map[string]string{"v": "true"},
+ }, {
+ "v: true",
+ map[string]interface{}{"v": true},
+ }, {
+ "v: 10",
+ map[string]interface{}{"v": 10},
+ }, {
+ "v: 0b10",
+ map[string]interface{}{"v": 2},
+ }, {
+ "v: 0xA",
+ map[string]interface{}{"v": 10},
+ }, {
+ "v: 4294967296",
+ map[string]int64{"v": 4294967296},
+ }, {
+ "v: 0.1",
+ map[string]interface{}{"v": 0.1},
+ }, {
+ "v: .1",
+ map[string]interface{}{"v": 0.1},
+ }, {
+ "v: .Inf",
+ map[string]interface{}{"v": math.Inf(+1)},
+ }, {
+ "v: -.Inf",
+ map[string]interface{}{"v": math.Inf(-1)},
+ }, {
+ "v: -10",
+ map[string]interface{}{"v": -10},
+ }, {
+ "v: -.1",
+ map[string]interface{}{"v": -0.1},
+ },
+
+ // Simple values.
+ {
+ "123",
+ &unmarshalIntTest,
+ },
+
+ // Floats from spec
+ {
+ "canonical: 6.8523e+5",
+ map[string]interface{}{"canonical": 6.8523e+5},
+ }, {
+ "expo: 685.230_15e+03",
+ map[string]interface{}{"expo": 685.23015e+03},
+ }, {
+ "fixed: 685_230.15",
+ map[string]interface{}{"fixed": 685230.15},
+ }, {
+ "neginf: -.inf",
+ map[string]interface{}{"neginf": math.Inf(-1)},
+ }, {
+ "fixed: 685_230.15",
+ map[string]float64{"fixed": 685230.15},
+ },
+ //{"sexa: 190:20:30.15", map[string]interface{}{"sexa": 0}}, // Unsupported
+ //{"notanum: .NaN", map[string]interface{}{"notanum": math.NaN()}}, // Equality of NaN fails.
+
+ // Bools are per 1.2 spec.
+ {
+ "canonical: true",
+ map[string]interface{}{"canonical": true},
+ }, {
+ "canonical: false",
+ map[string]interface{}{"canonical": false},
+ }, {
+ "bool: True",
+ map[string]interface{}{"bool": true},
+ }, {
+ "bool: False",
+ map[string]interface{}{"bool": false},
+ }, {
+ "bool: TRUE",
+ map[string]interface{}{"bool": true},
+ }, {
+ "bool: FALSE",
+ map[string]interface{}{"bool": false},
+ },
+ // For backwards compatibility with 1.1, decoding old strings into typed values still works.
+ {
+ "option: on",
+ map[string]bool{"option": true},
+ }, {
+ "option: y",
+ map[string]bool{"option": true},
+ }, {
+ "option: Off",
+ map[string]bool{"option": false},
+ }, {
+ "option: No",
+ map[string]bool{"option": false},
+ }, {
+ "option: other",
+ map[string]bool{},
+ },
+ // Ints from spec
+ {
+ "canonical: 685230",
+ map[string]interface{}{"canonical": 685230},
+ }, {
+ "decimal: +685_230",
+ map[string]interface{}{"decimal": 685230},
+ }, {
+ "octal: 02472256",
+ map[string]interface{}{"octal": 685230},
+ }, {
+ "octal: -02472256",
+ map[string]interface{}{"octal": -685230},
+ }, {
+ "octal: 0o2472256",
+ map[string]interface{}{"octal": 685230},
+ }, {
+ "octal: -0o2472256",
+ map[string]interface{}{"octal": -685230},
+ }, {
+ "hexa: 0x_0A_74_AE",
+ map[string]interface{}{"hexa": 685230},
+ }, {
+ "bin: 0b1010_0111_0100_1010_1110",
+ map[string]interface{}{"bin": 685230},
+ }, {
+ "bin: -0b101010",
+ map[string]interface{}{"bin": -42},
+ }, {
+ "bin: -0b1000000000000000000000000000000000000000000000000000000000000000",
+ map[string]interface{}{"bin": -9223372036854775808},
+ }, {
+ "decimal: +685_230",
+ map[string]int{"decimal": 685230},
+ },
+
+ //{"sexa: 190:20:30", map[string]interface{}{"sexa": 0}}, // Unsupported
+
+ // Nulls from spec
+ {
+ "empty:",
+ map[string]interface{}{"empty": nil},
+ }, {
+ "canonical: ~",
+ map[string]interface{}{"canonical": nil},
+ }, {
+ "english: null",
+ map[string]interface{}{"english": nil},
+ }, {
+ "~: null key",
+ map[interface{}]string{nil: "null key"},
+ }, {
+ "empty:",
+ map[string]*bool{"empty": nil},
+ },
+
+ // Flow sequence
+ {
+ "seq: [A,B]",
+ map[string]interface{}{"seq": []interface{}{"A", "B"}},
+ }, {
+ "seq: [A,B,C,]",
+ map[string][]string{"seq": []string{"A", "B", "C"}},
+ }, {
+ "seq: [A,1,C]",
+ map[string][]string{"seq": []string{"A", "1", "C"}},
+ }, {
+ "seq: [A,1,C]",
+ map[string][]int{"seq": []int{1}},
+ }, {
+ "seq: [A,1,C]",
+ map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
+ },
+ // Block sequence
+ {
+ "seq:\n - A\n - B",
+ map[string]interface{}{"seq": []interface{}{"A", "B"}},
+ }, {
+ "seq:\n - A\n - B\n - C",
+ map[string][]string{"seq": []string{"A", "B", "C"}},
+ }, {
+ "seq:\n - A\n - 1\n - C",
+ map[string][]string{"seq": []string{"A", "1", "C"}},
+ }, {
+ "seq:\n - A\n - 1\n - C",
+ map[string][]int{"seq": []int{1}},
+ }, {
+ "seq:\n - A\n - 1\n - C",
+ map[string]interface{}{"seq": []interface{}{"A", 1, "C"}},
+ },
+
+ // Literal block scalar
+ {
+ "scalar: | # Comment\n\n literal\n\n \ttext\n\n",
+ map[string]string{"scalar": "\nliteral\n\n\ttext\n"},
+ },
+
+ // Folded block scalar
+ {
+ "scalar: > # Comment\n\n folded\n line\n \n next\n line\n * one\n * two\n\n last\n line\n\n",
+ map[string]string{"scalar": "\nfolded line\nnext line\n * one\n * two\n\nlast line\n"},
+ },
+
+ // Map inside interface with no type hints.
+ {
+ "a: {b: c}",
+ map[interface{}]interface{}{"a": map[string]interface{}{"b": "c"}},
+ },
+ // Non-string map inside interface with no type hints.
+ {
+ "a: {b: c, 1: d}",
+ map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": "c", 1: "d"}},
+ },
+
+ // Structs and type conversions.
+ {
+ "hello: world",
+ &struct{ Hello string }{"world"},
+ }, {
+ "a: {b: c}",
+ &struct{ A struct{ B string } }{struct{ B string }{"c"}},
+ }, {
+ "a: {b: c}",
+ &struct{ A *struct{ B string } }{&struct{ B string }{"c"}},
+ }, {
+ "a: 'null'",
+ &struct{ A *unmarshalerType }{&unmarshalerType{"null"}},
+ }, {
+ "a: {b: c}",
+ &struct{ A map[string]string }{map[string]string{"b": "c"}},
+ }, {
+ "a: {b: c}",
+ &struct{ A *map[string]string }{&map[string]string{"b": "c"}},
+ }, {
+ "a:",
+ &struct{ A map[string]string }{},
+ }, {
+ "a: 1",
+ &struct{ A int }{1},
+ }, {
+ "a: 1",
+ &struct{ A float64 }{1},
+ }, {
+ "a: 1.0",
+ &struct{ A int }{1},
+ }, {
+ "a: 1.0",
+ &struct{ A uint }{1},
+ }, {
+ "a: [1, 2]",
+ &struct{ A []int }{[]int{1, 2}},
+ }, {
+ "a: [1, 2]",
+ &struct{ A [2]int }{[2]int{1, 2}},
+ }, {
+ "a: 1",
+ &struct{ B int }{0},
+ }, {
+ "a: 1",
+ &struct {
+ B int "a"
+ }{1},
+ }, {
+ // Some limited backwards compatibility with the 1.1 spec.
+ "a: YES",
+ &struct{ A bool }{true},
+ },
+
+ // Some cross type conversions
+ {
+ "v: 42",
+ map[string]uint{"v": 42},
+ }, {
+ "v: -42",
+ map[string]uint{},
+ }, {
+ "v: 4294967296",
+ map[string]uint64{"v": 4294967296},
+ }, {
+ "v: -4294967296",
+ map[string]uint64{},
+ },
+
+ // int
+ {
+ "int_max: 2147483647",
+ map[string]int{"int_max": math.MaxInt32},
+ },
+ {
+ "int_min: -2147483648",
+ map[string]int{"int_min": math.MinInt32},
+ },
+ {
+ "int_overflow: 9223372036854775808", // math.MaxInt64 + 1
+ map[string]int{},
+ },
+
+ // int64
+ {
+ "int64_max: 9223372036854775807",
+ map[string]int64{"int64_max": math.MaxInt64},
+ },
+ {
+ "int64_max_base2: 0b111111111111111111111111111111111111111111111111111111111111111",
+ map[string]int64{"int64_max_base2": math.MaxInt64},
+ },
+ {
+ "int64_min: -9223372036854775808",
+ map[string]int64{"int64_min": math.MinInt64},
+ },
+ {
+ "int64_neg_base2: -0b111111111111111111111111111111111111111111111111111111111111111",
+ map[string]int64{"int64_neg_base2": -math.MaxInt64},
+ },
+ {
+ "int64_overflow: 9223372036854775808", // math.MaxInt64 + 1
+ map[string]int64{},
+ },
+
+ // uint
+ {
+ "uint_min: 0",
+ map[string]uint{"uint_min": 0},
+ },
+ {
+ "uint_max: 4294967295",
+ map[string]uint{"uint_max": math.MaxUint32},
+ },
+ {
+ "uint_underflow: -1",
+ map[string]uint{},
+ },
+
+ // uint64
+ {
+ "uint64_min: 0",
+ map[string]uint{"uint64_min": 0},
+ },
+ {
+ "uint64_max: 18446744073709551615",
+ map[string]uint64{"uint64_max": math.MaxUint64},
+ },
+ {
+ "uint64_max_base2: 0b1111111111111111111111111111111111111111111111111111111111111111",
+ map[string]uint64{"uint64_max_base2": math.MaxUint64},
+ },
+ {
+ "uint64_maxint64: 9223372036854775807",
+ map[string]uint64{"uint64_maxint64": math.MaxInt64},
+ },
+ {
+ "uint64_underflow: -1",
+ map[string]uint64{},
+ },
+
+ // float32
+ {
+ "float32_max: 3.40282346638528859811704183484516925440e+38",
+ map[string]float32{"float32_max": math.MaxFloat32},
+ },
+ {
+ "float32_nonzero: 1.401298464324817070923729583289916131280e-45",
+ map[string]float32{"float32_nonzero": math.SmallestNonzeroFloat32},
+ },
+ {
+ "float32_maxuint64: 18446744073709551615",
+ map[string]float32{"float32_maxuint64": float32(math.MaxUint64)},
+ },
+ {
+ "float32_maxuint64+1: 18446744073709551616",
+ map[string]float32{"float32_maxuint64+1": float32(math.MaxUint64 + 1)},
+ },
+
+ // float64
+ {
+ "float64_max: 1.797693134862315708145274237317043567981e+308",
+ map[string]float64{"float64_max": math.MaxFloat64},
+ },
+ {
+ "float64_nonzero: 4.940656458412465441765687928682213723651e-324",
+ map[string]float64{"float64_nonzero": math.SmallestNonzeroFloat64},
+ },
+ {
+ "float64_maxuint64: 18446744073709551615",
+ map[string]float64{"float64_maxuint64": float64(math.MaxUint64)},
+ },
+ {
+ "float64_maxuint64+1: 18446744073709551616",
+ map[string]float64{"float64_maxuint64+1": float64(math.MaxUint64 + 1)},
+ },
+
+ // Overflow cases.
+ {
+ "v: 4294967297",
+ map[string]int32{},
+ }, {
+ "v: 128",
+ map[string]int8{},
+ },
+
+ // Quoted values.
+ {
+ "'1': '\"2\"'",
+ map[interface{}]interface{}{"1": "\"2\""},
+ }, {
+ "v:\n- A\n- 'B\n\n C'\n",
+ map[string][]string{"v": []string{"A", "B\nC"}},
+ },
+
+ // Explicit tags.
+ {
+ "v: !!float '1.1'",
+ map[string]interface{}{"v": 1.1},
+ }, {
+ "v: !!float 0",
+ map[string]interface{}{"v": float64(0)},
+ }, {
+ "v: !!float -1",
+ map[string]interface{}{"v": float64(-1)},
+ }, {
+ "v: !!null ''",
+ map[string]interface{}{"v": nil},
+ }, {
+ "%TAG !y! tag:yaml.org,2002:\n---\nv: !y!int '1'",
+ map[string]interface{}{"v": 1},
+ },
+
+ // Non-specific tag (Issue #75)
+ {
+ "v: ! test",
+ map[string]interface{}{"v": "test"},
+ },
+
+ // Anchors and aliases.
+ {
+ "a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
+ &struct{ A, B, C, D int }{1, 2, 1, 2},
+ }, {
+ "a: &a {c: 1}\nb: *a",
+ &struct {
+ A, B struct {
+ C int
+ }
+ }{struct{ C int }{1}, struct{ C int }{1}},
+ }, {
+ "a: &a [1, 2]\nb: *a",
+ &struct{ B []int }{[]int{1, 2}},
+ },
+
+ // Bug #1133337
+ {
+ "foo: ''",
+ map[string]*string{"foo": new(string)},
+ }, {
+ "foo: null",
+ map[string]*string{"foo": nil},
+ }, {
+ "foo: null",
+ map[string]string{"foo": ""},
+ }, {
+ "foo: null",
+ map[string]interface{}{"foo": nil},
+ },
+
+ // Support for ~
+ {
+ "foo: ~",
+ map[string]*string{"foo": nil},
+ }, {
+ "foo: ~",
+ map[string]string{"foo": ""},
+ }, {
+ "foo: ~",
+ map[string]interface{}{"foo": nil},
+ },
+
+ // Ignored field
+ {
+ "a: 1\nb: 2\n",
+ &struct {
+ A int
+ B int "-"
+ }{1, 0},
+ },
+
+ // Bug #1191981
+ {
+ "" +
+ "%YAML 1.1\n" +
+ "--- !!str\n" +
+ `"Generic line break (no glyph)\n\` + "\n" +
+ ` Generic line break (glyphed)\n\` + "\n" +
+ ` Line separator\u2028\` + "\n" +
+ ` Paragraph separator\u2029"` + "\n",
+ "" +
+ "Generic line break (no glyph)\n" +
+ "Generic line break (glyphed)\n" +
+ "Line separator\u2028Paragraph separator\u2029",
+ },
+
+ // Struct inlining
+ {
+ "a: 1\nb: 2\nc: 3\n",
+ &struct {
+ A int
+ C inlineB `yaml:",inline"`
+ }{1, inlineB{2, inlineC{3}}},
+ },
+
+ // Struct inlining as a pointer.
+ {
+ "a: 1\nb: 2\nc: 3\n",
+ &struct {
+ A int
+ C *inlineB `yaml:",inline"`
+ }{1, &inlineB{2, inlineC{3}}},
+ }, {
+ "a: 1\n",
+ &struct {
+ A int
+ C *inlineB `yaml:",inline"`
+ }{1, nil},
+ }, {
+ "a: 1\nc: 3\nd: 4\n",
+ &struct {
+ A int
+ C *inlineD `yaml:",inline"`
+ }{1, &inlineD{&inlineC{3}, 4}},
+ },
+
+ // Map inlining
+ {
+ "a: 1\nb: 2\nc: 3\n",
+ &struct {
+ A int
+ C map[string]int `yaml:",inline"`
+ }{1, map[string]int{"b": 2, "c": 3}},
+ },
+
+ // bug 1243827
+ {
+ "a: -b_c",
+ map[string]interface{}{"a": "-b_c"},
+ },
+ {
+ "a: +b_c",
+ map[string]interface{}{"a": "+b_c"},
+ },
+ {
+ "a: 50cent_of_dollar",
+ map[string]interface{}{"a": "50cent_of_dollar"},
+ },
+
+ // issue #295 (allow scalars with colons in flow mappings and sequences)
+ {
+ "a: {b: https://github.com/go-yaml/yaml}",
+ map[string]interface{}{"a": map[string]interface{}{
+ "b": "https://github.com/go-yaml/yaml",
+ }},
+ },
+ {
+ "a: [https://github.com/go-yaml/yaml]",
+ map[string]interface{}{"a": []interface{}{"https://github.com/go-yaml/yaml"}},
+ },
+
+ // Duration
+ {
+ "a: 3s",
+ map[string]time.Duration{"a": 3 * time.Second},
+ },
+
+ // Issue #24.
+ {
+ "a: ",
+ map[string]string{"a": ""},
+ },
+
+ // Base 60 floats are obsolete and unsupported.
+ {
+ "a: 1:1\n",
+ map[string]string{"a": "1:1"},
+ },
+
+ // Binary data.
+ {
+ "a: !!binary gIGC\n",
+ map[string]string{"a": "\x80\x81\x82"},
+ }, {
+ "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
+ map[string]string{"a": strings.Repeat("\x90", 54)},
+ }, {
+ "a: !!binary |\n " + strings.Repeat("A", 70) + "\n ==\n",
+ map[string]string{"a": strings.Repeat("\x00", 52)},
+ },
+
+ // Issue #39.
+ {
+ "a:\n b:\n c: d\n",
+ map[string]struct{ B interface{} }{"a": {map[string]interface{}{"c": "d"}}},
+ },
+
+ // Custom map type.
+ {
+ "a: {b: c}",
+ M{"a": M{"b": "c"}},
+ },
+
+ // Support encoding.TextUnmarshaler.
+ {
+ "a: 1.2.3.4\n",
+ map[string]textUnmarshaler{"a": textUnmarshaler{S: "1.2.3.4"}},
+ },
+ {
+ "a: 2015-02-24T18:19:39Z\n",
+ map[string]textUnmarshaler{"a": textUnmarshaler{"2015-02-24T18:19:39Z"}},
+ },
+
+ // Timestamps
+ {
+ // Date only.
+ "a: 2015-01-01\n",
+ map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+ },
+ {
+ // RFC3339
+ "a: 2015-02-24T18:19:39.12Z\n",
+ map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, .12e9, time.UTC)},
+ },
+ {
+ // RFC3339 with short dates.
+ "a: 2015-2-3T3:4:5Z",
+ map[string]time.Time{"a": time.Date(2015, 2, 3, 3, 4, 5, 0, time.UTC)},
+ },
+ {
+ // ISO8601 lower case t
+ "a: 2015-02-24t18:19:39Z\n",
+ map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
+ },
+ {
+ // space separate, no time zone
+ "a: 2015-02-24 18:19:39\n",
+ map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
+ },
+ // Some cases not currently handled. Uncomment these when
+ // the code is fixed.
+ // {
+ // // space separated with time zone
+ // "a: 2001-12-14 21:59:43.10 -5",
+ // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
+ // },
+ // {
+ // // arbitrary whitespace between fields
+ // "a: 2001-12-14 \t\t \t21:59:43.10 \t Z",
+ // map[string]interface{}{"a": time.Date(2001, 12, 14, 21, 59, 43, .1e9, time.UTC)},
+ // },
+ {
+ // explicit string tag
+ "a: !!str 2015-01-01",
+ map[string]interface{}{"a": "2015-01-01"},
+ },
+ {
+ // explicit timestamp tag on quoted string
+ "a: !!timestamp \"2015-01-01\"",
+ map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+ },
+ {
+ // explicit timestamp tag on unquoted string
+ "a: !!timestamp 2015-01-01",
+ map[string]time.Time{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+ },
+ {
+ // quoted string that's a valid timestamp
+ "a: \"2015-01-01\"",
+ map[string]interface{}{"a": "2015-01-01"},
+ },
+ {
+ // explicit timestamp tag into interface.
+ "a: !!timestamp \"2015-01-01\"",
+ map[string]interface{}{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+ },
+ {
+ // implicit timestamp tag into interface.
+ "a: 2015-01-01",
+ map[string]interface{}{"a": time.Date(2015, 1, 1, 0, 0, 0, 0, time.UTC)},
+ },
+
+ // Encode empty lists as zero-length slices.
+ {
+ "a: []",
+ &struct{ A []int }{[]int{}},
+ },
+
+ // UTF-16-LE
+ {
+ "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n\x00",
+ M{"ñoño": "very yes"},
+ },
+ // UTF-16-LE with surrogate.
+ {
+ "\xff\xfe\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \x00=\xd8\xd4\xdf\n\x00",
+ M{"ñoño": "very yes 🟔"},
+ },
+
+ // UTF-16-BE
+ {
+ "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00\n",
+ M{"ñoño": "very yes"},
+ },
+ // UTF-16-BE with surrogate.
+ {
+ "\xfe\xff\x00\xf1\x00o\x00\xf1\x00o\x00:\x00 \x00v\x00e\x00r\x00y\x00 \x00y\x00e\x00s\x00 \xd8=\xdf\xd4\x00\n",
+ M{"ñoño": "very yes 🟔"},
+ },
+
+ // This *is* in fact a float number, per the spec. #171 was a mistake.
+ {
+ "a: 123456e1\n",
+ M{"a": 123456e1},
+ }, {
+ "a: 123456E1\n",
+ M{"a": 123456E1},
+ },
+ // yaml-test-suite 3GZX: Spec Example 7.1. Alias Nodes
+ {
+ "First occurrence: &anchor Foo\nSecond occurrence: *anchor\nOverride anchor: &anchor Bar\nReuse anchor: *anchor\n",
+ map[string]interface{}{
+ "First occurrence": "Foo",
+ "Second occurrence": "Foo",
+ "Override anchor": "Bar",
+ "Reuse anchor": "Bar",
+ },
+ },
+ // Single document with garbage following it.
+ {
+ "---\nhello\n...\n}not yaml",
+ "hello",
+ },
+
+ // Comment scan exhausting the input buffer (issue #469).
+ {
+ "true\n#" + strings.Repeat(" ", 512*3),
+ "true",
+ }, {
+ "true #" + strings.Repeat(" ", 512*3),
+ "true",
+ },
+
+ // CRLF
+ {
+ "a: b\r\nc:\r\n- d\r\n- e\r\n",
+ map[string]interface{}{
+ "a": "b",
+ "c": []interface{}{"d", "e"},
+ },
+ },
+
+}
+
+type M map[string]interface{}
+
+type inlineB struct {
+ B int
+ inlineC `yaml:",inline"`
+}
+
+type inlineC struct {
+ C int
+}
+
+type inlineD struct {
+ C *inlineC `yaml:",inline"`
+ D int
+}
+
+func (s *S) TestUnmarshal(c *C) {
+ for i, item := range unmarshalTests {
+ c.Logf("test %d: %q", i, item.data)
+ t := reflect.ValueOf(item.value).Type()
+ value := reflect.New(t)
+ err := yaml.Unmarshal([]byte(item.data), value.Interface())
+ if _, ok := err.(*yaml.TypeError); !ok {
+ c.Assert(err, IsNil)
+ }
+ c.Assert(value.Elem().Interface(), DeepEquals, item.value, Commentf("error: %v", err))
+ }
+}
+
+func (s *S) TestUnmarshalFullTimestamp(c *C) {
+ // Full timestamp in same format as encoded. This is confirmed to be
+ // properly decoded by Python as a timestamp as well.
+ var str = "2015-02-24T18:19:39.123456789-03:00"
+ var t interface{}
+ err := yaml.Unmarshal([]byte(str), &t)
+ c.Assert(err, IsNil)
+ c.Assert(t, Equals, time.Date(2015, 2, 24, 18, 19, 39, 123456789, t.(time.Time).Location()))
+ c.Assert(t.(time.Time).In(time.UTC), Equals, time.Date(2015, 2, 24, 21, 19, 39, 123456789, time.UTC))
+}
+
+func (s *S) TestDecoderSingleDocument(c *C) {
+ // Test that Decoder.Decode works as expected on
+ // all the unmarshal tests.
+ for i, item := range unmarshalTests {
+ c.Logf("test %d: %q", i, item.data)
+ if item.data == "" {
+ // Behaviour differs when there's no YAML.
+ continue
+ }
+ t := reflect.ValueOf(item.value).Type()
+ value := reflect.New(t)
+ err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(value.Interface())
+ if _, ok := err.(*yaml.TypeError); !ok {
+ c.Assert(err, IsNil)
+ }
+ c.Assert(value.Elem().Interface(), DeepEquals, item.value)
+ }
+}
+
+var decoderTests = []struct {
+ data string
+ values []interface{}
+}{{
+ "",
+ nil,
+}, {
+ "a: b",
+ []interface{}{
+ map[string]interface{}{"a": "b"},
+ },
+}, {
+ "---\na: b\n...\n",
+ []interface{}{
+ map[string]interface{}{"a": "b"},
+ },
+}, {
+ "---\n'hello'\n...\n---\ngoodbye\n...\n",
+ []interface{}{
+ "hello",
+ "goodbye",
+ },
+}}
+
+func (s *S) TestDecoder(c *C) {
+ for i, item := range decoderTests {
+ c.Logf("test %d: %q", i, item.data)
+ var values []interface{}
+ dec := yaml.NewDecoder(strings.NewReader(item.data))
+ for {
+ var value interface{}
+ err := dec.Decode(&value)
+ if err == io.EOF {
+ break
+ }
+ c.Assert(err, IsNil)
+ values = append(values, value)
+ }
+ c.Assert(values, DeepEquals, item.values)
+ }
+}
+
+type errReader struct{}
+
+func (errReader) Read([]byte) (int, error) {
+ return 0, errors.New("some read error")
+}
+
+func (s *S) TestDecoderReadError(c *C) {
+ err := yaml.NewDecoder(errReader{}).Decode(&struct{}{})
+ c.Assert(err, ErrorMatches, `yaml: input error: some read error`)
+}
+
+func (s *S) TestUnmarshalNaN(c *C) {
+ value := map[string]interface{}{}
+ err := yaml.Unmarshal([]byte("notanum: .NaN"), &value)
+ c.Assert(err, IsNil)
+ c.Assert(math.IsNaN(value["notanum"].(float64)), Equals, true)
+}
+
+func (s *S) TestUnmarshalDurationInt(c *C) {
+ // Don't accept plain ints as durations as it's unclear (issue #200).
+ var d time.Duration
+ err := yaml.Unmarshal([]byte("123"), &d)
+ c.Assert(err, ErrorMatches, "(?s).* line 1: cannot unmarshal !!int `123` into time.Duration")
+}
+
+var unmarshalErrorTests = []struct {
+ data, error string
+}{
+ {"v: !!float 'error'", "yaml: cannot decode !!str `error` as a !!float"},
+ {"v: [A,", "yaml: line 1: did not find expected node content"},
+ {"v:\n- [A,", "yaml: line 2: did not find expected node content"},
+ {"a:\n- b: *,", "yaml: line 2: did not find expected alphabetic or numeric character"},
+ {"a: *b\n", "yaml: unknown anchor 'b' referenced"},
+ {"a: &a\n b: *a\n", "yaml: anchor 'a' value contains itself"},
+ {"value: -", "yaml: block sequence entries are not allowed in this context"},
+ {"a: !!binary ==", "yaml: !!binary value contains invalid base64 data"},
+ {"{[.]}", `yaml: invalid map key: \[\]interface \{\}\{"\."\}`},
+ {"{{.}}", `yaml: invalid map key: map\[string]interface \{\}\{".":interface \{\}\(nil\)\}`},
+ {"b: *a\na: &a {c: 1}", `yaml: unknown anchor 'a' referenced`},
+ {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
+ {"a:\n 1:\nb\n 2:", ".*could not find expected ':'"},
+ {"a: 1\nb: 2\nc 2\nd: 3\n", "^yaml: line 3: could not find expected ':'$"},
+ {
+ "a: &a [00,00,00,00,00,00,00,00,00]\n" +
+ "b: &b [*a,*a,*a,*a,*a,*a,*a,*a,*a]\n" +
+ "c: &c [*b,*b,*b,*b,*b,*b,*b,*b,*b]\n" +
+ "d: &d [*c,*c,*c,*c,*c,*c,*c,*c,*c]\n" +
+ "e: &e [*d,*d,*d,*d,*d,*d,*d,*d,*d]\n" +
+ "f: &f [*e,*e,*e,*e,*e,*e,*e,*e,*e]\n" +
+ "g: &g [*f,*f,*f,*f,*f,*f,*f,*f,*f]\n" +
+ "h: &h [*g,*g,*g,*g,*g,*g,*g,*g,*g]\n" +
+ "i: &i [*h,*h,*h,*h,*h,*h,*h,*h,*h]\n",
+ "yaml: document contains excessive aliasing",
+ },
+}
+
+func (s *S) TestUnmarshalErrors(c *C) {
+ for i, item := range unmarshalErrorTests {
+ c.Logf("test %d: %q", i, item.data)
+ var value interface{}
+ err := yaml.Unmarshal([]byte(item.data), &value)
+ c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
+ }
+}
+
+func (s *S) TestDecoderErrors(c *C) {
+ for _, item := range unmarshalErrorTests {
+ var value interface{}
+ err := yaml.NewDecoder(strings.NewReader(item.data)).Decode(&value)
+ c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
+ }
+}
+
+var unmarshalerTests = []struct {
+ data, tag string
+ value interface{}
+}{
+ {"_: {hi: there}", "!!map", map[string]interface{}{"hi": "there"}},
+ {"_: [1,A]", "!!seq", []interface{}{1, "A"}},
+ {"_: 10", "!!int", 10},
+ {"_: null", "!!null", nil},
+ {`_: BAR!`, "!!str", "BAR!"},
+ {`_: "BAR!"`, "!!str", "BAR!"},
+ {"_: !!foo 'BAR!'", "!!foo", "BAR!"},
+ {`_: ""`, "!!str", ""},
+}
+
+var unmarshalerResult = map[int]error{}
+
+type unmarshalerType struct {
+ value interface{}
+}
+
+func (o *unmarshalerType) UnmarshalYAML(value *yaml.Node) error {
+ if err := value.Decode(&o.value); err != nil {
+ return err
+ }
+ if i, ok := o.value.(int); ok {
+ if result, ok := unmarshalerResult[i]; ok {
+ return result
+ }
+ }
+ return nil
+}
+
+type unmarshalerPointer struct {
+ Field *unmarshalerType "_"
+}
+
+type unmarshalerValue struct {
+ Field unmarshalerType "_"
+}
+
+type unmarshalerInlined struct {
+ Field *unmarshalerType "_"
+ Inlined unmarshalerType `yaml:",inline"`
+}
+
+type unmarshalerInlinedTwice struct {
+ InlinedTwice unmarshalerInlined `yaml:",inline"`
+}
+
+type obsoleteUnmarshalerType struct {
+ value interface{}
+}
+
+func (o *obsoleteUnmarshalerType) UnmarshalYAML(unmarshal func(v interface{}) error) error {
+ if err := unmarshal(&o.value); err != nil {
+ return err
+ }
+ if i, ok := o.value.(int); ok {
+ if result, ok := unmarshalerResult[i]; ok {
+ return result
+ }
+ }
+ return nil
+}
+
+type obsoleteUnmarshalerPointer struct {
+ Field *obsoleteUnmarshalerType "_"
+}
+
+type obsoleteUnmarshalerValue struct {
+ Field obsoleteUnmarshalerType "_"
+}
+
+func (s *S) TestUnmarshalerPointerField(c *C) {
+ for _, item := range unmarshalerTests {
+ obj := &unmarshalerPointer{}
+ err := yaml.Unmarshal([]byte(item.data), obj)
+ c.Assert(err, IsNil)
+ if item.value == nil {
+ c.Assert(obj.Field, IsNil)
+ } else {
+ c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
+ c.Assert(obj.Field.value, DeepEquals, item.value)
+ }
+ }
+ for _, item := range unmarshalerTests {
+ obj := &obsoleteUnmarshalerPointer{}
+ err := yaml.Unmarshal([]byte(item.data), obj)
+ c.Assert(err, IsNil)
+ if item.value == nil {
+ c.Assert(obj.Field, IsNil)
+ } else {
+ c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
+ c.Assert(obj.Field.value, DeepEquals, item.value)
+ }
+ }
+}
+
+func (s *S) TestUnmarshalerValueField(c *C) {
+ for _, item := range unmarshalerTests {
+ obj := &obsoleteUnmarshalerValue{}
+ err := yaml.Unmarshal([]byte(item.data), obj)
+ c.Assert(err, IsNil)
+ c.Assert(obj.Field, NotNil, Commentf("Pointer not initialized (%#v)", item.value))
+ c.Assert(obj.Field.value, DeepEquals, item.value)
+ }
+}
+
+func (s *S) TestUnmarshalerInlinedField(c *C) {
+ obj := &unmarshalerInlined{}
+ err := yaml.Unmarshal([]byte("_: a\ninlined: b\n"), obj)
+ c.Assert(err, IsNil)
+ c.Assert(obj.Field, DeepEquals, &unmarshalerType{"a"})
+ c.Assert(obj.Inlined, DeepEquals, unmarshalerType{map[string]interface{}{"_": "a", "inlined": "b"}})
+
+ twc := &unmarshalerInlinedTwice{}
+ err = yaml.Unmarshal([]byte("_: a\ninlined: b\n"), twc)
+ c.Assert(err, IsNil)
+ c.Assert(twc.InlinedTwice.Field, DeepEquals, &unmarshalerType{"a"})
+ c.Assert(twc.InlinedTwice.Inlined, DeepEquals, unmarshalerType{map[string]interface{}{"_": "a", "inlined": "b"}})
+}
+
+func (s *S) TestUnmarshalerWholeDocument(c *C) {
+ obj := &obsoleteUnmarshalerType{}
+ err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
+ c.Assert(err, IsNil)
+ value, ok := obj.value.(map[string]interface{})
+ c.Assert(ok, Equals, true, Commentf("value: %#v", obj.value))
+ c.Assert(value["_"], DeepEquals, unmarshalerTests[0].value)
+}
+
+func (s *S) TestUnmarshalerTypeError(c *C) {
+ unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
+ unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
+ defer func() {
+ delete(unmarshalerResult, 2)
+ delete(unmarshalerResult, 4)
+ }()
+
+ type T struct {
+ Before int
+ After int
+ M map[string]*unmarshalerType
+ }
+ var v T
+ data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
+ err := yaml.Unmarshal([]byte(data), &v)
+ c.Assert(err, ErrorMatches, ""+
+ "yaml: unmarshal errors:\n"+
+ " line 1: cannot unmarshal !!str `A` into int\n"+
+ " foo\n"+
+ " bar\n"+
+ " line 1: cannot unmarshal !!str `B` into int")
+ c.Assert(v.M["abc"], NotNil)
+ c.Assert(v.M["def"], IsNil)
+ c.Assert(v.M["ghi"], NotNil)
+ c.Assert(v.M["jkl"], IsNil)
+
+ c.Assert(v.M["abc"].value, Equals, 1)
+ c.Assert(v.M["ghi"].value, Equals, 3)
+}
+
+func (s *S) TestObsoleteUnmarshalerTypeError(c *C) {
+ unmarshalerResult[2] = &yaml.TypeError{[]string{"foo"}}
+ unmarshalerResult[4] = &yaml.TypeError{[]string{"bar"}}
+ defer func() {
+ delete(unmarshalerResult, 2)
+ delete(unmarshalerResult, 4)
+ }()
+
+ type T struct {
+ Before int
+ After int
+ M map[string]*obsoleteUnmarshalerType
+ }
+ var v T
+ data := `{before: A, m: {abc: 1, def: 2, ghi: 3, jkl: 4}, after: B}`
+ err := yaml.Unmarshal([]byte(data), &v)
+ c.Assert(err, ErrorMatches, ""+
+ "yaml: unmarshal errors:\n"+
+ " line 1: cannot unmarshal !!str `A` into int\n"+
+ " foo\n"+
+ " bar\n"+
+ " line 1: cannot unmarshal !!str `B` into int")
+ c.Assert(v.M["abc"], NotNil)
+ c.Assert(v.M["def"], IsNil)
+ c.Assert(v.M["ghi"], NotNil)
+ c.Assert(v.M["jkl"], IsNil)
+
+ c.Assert(v.M["abc"].value, Equals, 1)
+ c.Assert(v.M["ghi"].value, Equals, 3)
+}
+
+type proxyTypeError struct{}
+
+func (v *proxyTypeError) UnmarshalYAML(node *yaml.Node) error {
+ var s string
+ var a int32
+ var b int64
+ if err := node.Decode(&s); err != nil {
+ panic(err)
+ }
+ if s == "a" {
+ if err := node.Decode(&b); err == nil {
+ panic("should have failed")
+ }
+ return node.Decode(&a)
+ }
+ if err := node.Decode(&a); err == nil {
+ panic("should have failed")
+ }
+ return node.Decode(&b)
+}
+
+func (s *S) TestUnmarshalerTypeErrorProxying(c *C) {
+ type T struct {
+ Before int
+ After int
+ M map[string]*proxyTypeError
+ }
+ var v T
+ data := `{before: A, m: {abc: a, def: b}, after: B}`
+ err := yaml.Unmarshal([]byte(data), &v)
+ c.Assert(err, ErrorMatches, ""+
+ "yaml: unmarshal errors:\n"+
+ " line 1: cannot unmarshal !!str `A` into int\n"+
+ " line 1: cannot unmarshal !!str `a` into int32\n"+
+ " line 1: cannot unmarshal !!str `b` into int64\n"+
+ " line 1: cannot unmarshal !!str `B` into int")
+}
+
+type obsoleteProxyTypeError struct{}
+
+func (v *obsoleteProxyTypeError) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var s string
+ var a int32
+ var b int64
+ if err := unmarshal(&s); err != nil {
+ panic(err)
+ }
+ if s == "a" {
+ if err := unmarshal(&b); err == nil {
+ panic("should have failed")
+ }
+ return unmarshal(&a)
+ }
+ if err := unmarshal(&a); err == nil {
+ panic("should have failed")
+ }
+ return unmarshal(&b)
+}
+
+func (s *S) TestObsoleteUnmarshalerTypeErrorProxying(c *C) {
+ type T struct {
+ Before int
+ After int
+ M map[string]*obsoleteProxyTypeError
+ }
+ var v T
+ data := `{before: A, m: {abc: a, def: b}, after: B}`
+ err := yaml.Unmarshal([]byte(data), &v)
+ c.Assert(err, ErrorMatches, ""+
+ "yaml: unmarshal errors:\n"+
+ " line 1: cannot unmarshal !!str `A` into int\n"+
+ " line 1: cannot unmarshal !!str `a` into int32\n"+
+ " line 1: cannot unmarshal !!str `b` into int64\n"+
+ " line 1: cannot unmarshal !!str `B` into int")
+}
+
+var failingErr = errors.New("failingErr")
+
+type failingUnmarshaler struct{}
+
+func (ft *failingUnmarshaler) UnmarshalYAML(node *yaml.Node) error {
+ return failingErr
+}
+
+func (s *S) TestUnmarshalerError(c *C) {
+ err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
+ c.Assert(err, Equals, failingErr)
+}
+
+type obsoleteFailingUnmarshaler struct{}
+
+func (ft *obsoleteFailingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ return failingErr
+}
+
+func (s *S) TestObsoleteUnmarshalerError(c *C) {
+ err := yaml.Unmarshal([]byte("a: b"), &obsoleteFailingUnmarshaler{})
+ c.Assert(err, Equals, failingErr)
+}
+
+type sliceUnmarshaler []int
+
+func (su *sliceUnmarshaler) UnmarshalYAML(node *yaml.Node) error {
+ var slice []int
+ err := node.Decode(&slice)
+ if err == nil {
+ *su = slice
+ return nil
+ }
+
+ var intVal int
+ err = node.Decode(&intVal)
+ if err == nil {
+ *su = []int{intVal}
+ return nil
+ }
+
+ return err
+}
+
+func (s *S) TestUnmarshalerRetry(c *C) {
+ var su sliceUnmarshaler
+ err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
+ c.Assert(err, IsNil)
+ c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1, 2, 3}))
+
+ err = yaml.Unmarshal([]byte("1"), &su)
+ c.Assert(err, IsNil)
+ c.Assert(su, DeepEquals, sliceUnmarshaler([]int{1}))
+}
+
+type obsoleteSliceUnmarshaler []int
+
+func (su *obsoleteSliceUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
+ var slice []int
+ err := unmarshal(&slice)
+ if err == nil {
+ *su = slice
+ return nil
+ }
+
+ var intVal int
+ err = unmarshal(&intVal)
+ if err == nil {
+ *su = []int{intVal}
+ return nil
+ }
+
+ return err
+}
+
+func (s *S) TestObsoleteUnmarshalerRetry(c *C) {
+ var su obsoleteSliceUnmarshaler
+ err := yaml.Unmarshal([]byte("[1, 2, 3]"), &su)
+ c.Assert(err, IsNil)
+ c.Assert(su, DeepEquals, obsoleteSliceUnmarshaler([]int{1, 2, 3}))
+
+ err = yaml.Unmarshal([]byte("1"), &su)
+ c.Assert(err, IsNil)
+ c.Assert(su, DeepEquals, obsoleteSliceUnmarshaler([]int{1}))
+}
+
+// From http://yaml.org/type/merge.html
+var mergeTests = `
+anchors:
+ list:
+ - &CENTER { "x": 1, "y": 2 }
+ - &LEFT { "x": 0, "y": 2 }
+ - &BIG { "r": 10 }
+ - &SMALL { "r": 1 }
+
+# All the following maps are equal:
+
+plain:
+ # Explicit keys
+ "x": 1
+ "y": 2
+ "r": 10
+ label: center/big
+
+mergeOne:
+ # Merge one map
+ << : *CENTER
+ "r": 10
+ label: center/big
+
+mergeMultiple:
+ # Merge multiple maps
+ << : [ *CENTER, *BIG ]
+ label: center/big
+
+override:
+ # Override
+ << : [ *BIG, *LEFT, *SMALL ]
+ "x": 1
+ label: center/big
+
+shortTag:
+ # Explicit short merge tag
+ !!merge "<<" : [ *CENTER, *BIG ]
+ label: center/big
+
+longTag:
+ # Explicit merge long tag
+ ! "<<" : [ *CENTER, *BIG ]
+ label: center/big
+
+inlineMap:
+ # Inlined map
+ << : {"x": 1, "y": 2, "r": 10}
+ label: center/big
+
+inlineSequenceMap:
+ # Inlined map in sequence
+ << : [ *CENTER, {"r": 10} ]
+ label: center/big
+`
+
+func (s *S) TestMerge(c *C) {
+ var want = map[interface{}]interface{}{
+ "x": 1,
+ "y": 2,
+ "r": 10,
+ "label": "center/big",
+ }
+
+ wantStringMap := make(map[string]interface{})
+ for k, v := range want {
+ wantStringMap[fmt.Sprintf("%v", k)] = v
+ }
+
+ var m map[interface{}]interface{}
+ err := yaml.Unmarshal([]byte(mergeTests), &m)
+ c.Assert(err, IsNil)
+ for name, test := range m {
+ if name == "anchors" {
+ continue
+ }
+ if name == "plain" {
+ c.Assert(test, DeepEquals, wantStringMap, Commentf("test %q failed", name))
+ continue
+ }
+ c.Assert(test, DeepEquals, want, Commentf("test %q failed", name))
+ }
+}
+
+func (s *S) TestMergeStruct(c *C) {
+ type Data struct {
+ X, Y, R int
+ Label string
+ }
+ want := Data{1, 2, 10, "center/big"}
+
+ var m map[string]Data
+ err := yaml.Unmarshal([]byte(mergeTests), &m)
+ c.Assert(err, IsNil)
+ for name, test := range m {
+ if name == "anchors" {
+ continue
+ }
+ c.Assert(test, Equals, want, Commentf("test %q failed", name))
+ }
+}
+
+var unmarshalNullTests = []struct{ input string; pristine, expected func() interface{} }{{
+ "null",
+ func() interface{} { var v interface{}; v = "v"; return &v },
+ func() interface{} { var v interface{}; v = nil; return &v },
+}, {
+ "null",
+ func() interface{} { var s = "s"; return &s },
+ func() interface{} { var s = "s"; return &s },
+}, {
+ "null",
+ func() interface{} { var s = "s"; sptr := &s; return &sptr },
+ func() interface{} { var sptr *string; return &sptr },
+}, {
+ "null",
+ func() interface{} { var i = 1; return &i },
+ func() interface{} { var i = 1; return &i },
+}, {
+ "null",
+ func() interface{} { var i = 1; iptr := &i; return &iptr },
+ func() interface{} { var iptr *int; return &iptr },
+}, {
+ "null",
+ func() interface{} { var m = map[string]int{"s": 1}; return &m },
+ func() interface{} { var m map[string]int; return &m },
+}, {
+ "null",
+ func() interface{} { var m = map[string]int{"s": 1}; return m },
+ func() interface{} { var m = map[string]int{"s": 1}; return m },
+}, {
+ "s2: null\ns3: null",
+ func() interface{} { var m = map[string]int{"s1": 1, "s2": 2}; return m },
+ func() interface{} { var m = map[string]int{"s1": 1, "s2": 2, "s3": 0}; return m },
+}, {
+ "s2: null\ns3: null",
+ func() interface{} { var m = map[string]interface{}{"s1": 1, "s2": 2}; return m },
+ func() interface{} { var m = map[string]interface{}{"s1": 1, "s2": nil, "s3": nil}; return m },
+}}
+
+func (s *S) TestUnmarshalNull(c *C) {
+ for _, test := range unmarshalNullTests {
+ pristine := test.pristine()
+ expected := test.expected()
+ err := yaml.Unmarshal([]byte(test.input), pristine)
+ c.Assert(err, IsNil)
+ c.Assert(pristine, DeepEquals, expected)
+ }
+}
+
+func (s *S) TestUnmarshalPreservesData(c *C) {
+ var v struct {
+ A, B int
+ C int `yaml:"-"`
+ }
+ v.A = 42
+ v.C = 88
+ err := yaml.Unmarshal([]byte("---"), &v)
+ c.Assert(err, IsNil)
+ c.Assert(v.A, Equals, 42)
+ c.Assert(v.B, Equals, 0)
+ c.Assert(v.C, Equals, 88)
+
+ err = yaml.Unmarshal([]byte("b: 21\nc: 99"), &v)
+ c.Assert(err, IsNil)
+ c.Assert(v.A, Equals, 42)
+ c.Assert(v.B, Equals, 21)
+ c.Assert(v.C, Equals, 88)
+}
+
+func (s *S) TestUnmarshalSliceOnPreset(c *C) {
+ // Issue #48.
+ v := struct{ A []int }{[]int{1}}
+ yaml.Unmarshal([]byte("a: [2]"), &v)
+ c.Assert(v.A, DeepEquals, []int{2})
+}
+
+var unmarshalStrictTests = []struct {
+ known bool
+ unique bool
+ data string
+ value interface{}
+ error string
+}{{
+ known: true,
+ data: "a: 1\nc: 2\n",
+ value: struct{ A, B int }{A: 1},
+ error: `yaml: unmarshal errors:\n line 2: field c not found in type struct { A int; B int }`,
+}, {
+ unique: true,
+ data: "a: 1\nb: 2\na: 3\n",
+ value: struct{ A, B int }{A: 3, B: 2},
+ error: `yaml: unmarshal errors:\n line 3: mapping key "a" already defined at line 1`,
+}, {
+ unique: true,
+ data: "c: 3\na: 1\nb: 2\nc: 4\n",
+ value: struct {
+ A int
+ inlineB `yaml:",inline"`
+ }{
+ A: 1,
+ inlineB: inlineB{
+ B: 2,
+ inlineC: inlineC{
+ C: 4,
+ },
+ },
+ },
+ error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`,
+}, {
+ unique: true,
+ data: "c: 0\na: 1\nb: 2\nc: 1\n",
+ value: struct {
+ A int
+ inlineB `yaml:",inline"`
+ }{
+ A: 1,
+ inlineB: inlineB{
+ B: 2,
+ inlineC: inlineC{
+ C: 1,
+ },
+ },
+ },
+ error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`,
+}, {
+ unique: true,
+ data: "c: 1\na: 1\nb: 2\nc: 3\n",
+ value: struct {
+ A int
+ M map[string]interface{} `yaml:",inline"`
+ }{
+ A: 1,
+ M: map[string]interface{}{
+ "b": 2,
+ "c": 3,
+ },
+ },
+ error: `yaml: unmarshal errors:\n line 4: mapping key "c" already defined at line 1`,
+}, {
+ unique: true,
+ data: "a: 1\n9: 2\nnull: 3\n9: 4",
+ value: map[interface{}]interface{}{
+ "a": 1,
+ nil: 3,
+ 9: 4,
+ },
+ error: `yaml: unmarshal errors:\n line 4: mapping key "9" already defined at line 2`,
+}}
+
+func (s *S) TestUnmarshalKnownFields(c *C) {
+ for i, item := range unmarshalStrictTests {
+ c.Logf("test %d: %q", i, item.data)
+ // First test that normal Unmarshal unmarshals to the expected value.
+ if !item.unique {
+ t := reflect.ValueOf(item.value).Type()
+ value := reflect.New(t)
+ err := yaml.Unmarshal([]byte(item.data), value.Interface())
+ c.Assert(err, Equals, nil)
+ c.Assert(value.Elem().Interface(), DeepEquals, item.value)
+ }
+
+ // Then test that it fails on the same thing with KnownFields on.
+ t := reflect.ValueOf(item.value).Type()
+ value := reflect.New(t)
+ dec := yaml.NewDecoder(bytes.NewBuffer([]byte(item.data)))
+ dec.KnownFields(item.known)
+ err := dec.Decode(value.Interface())
+ c.Assert(err, ErrorMatches, item.error)
+ }
+}
+
+type textUnmarshaler struct {
+ S string
+}
+
+func (t *textUnmarshaler) UnmarshalText(s []byte) error {
+ t.S = string(s)
+ return nil
+}
+
+func (s *S) TestFuzzCrashers(c *C) {
+ cases := []string{
+ // runtime error: index out of range
+ "\"\\0\\\r\n",
+
+ // should not happen
+ " 0: [\n] 0",
+ "? ? \"\n\" 0",
+ " - {\n000}0",
+ "0:\n 0: [0\n] 0",
+ " - \"\n000\"0",
+ " - \"\n000\"\"",
+ "0:\n - {\n000}0",
+ "0:\n - \"\n000\"0",
+ "0:\n - \"\n000\"\"",
+
+ // runtime error: index out of range
+ " \ufeff\n",
+ "? \ufeff\n",
+ "? \ufeff:\n",
+ "0: \ufeff\n",
+ "? \ufeff: \ufeff\n",
+ }
+ for _, data := range cases {
+ var v interface{}
+ _ = yaml.Unmarshal([]byte(data), &v)
+ }
+}
+
+//var data []byte
+//func init() {
+// var err error
+// data, err = ioutil.ReadFile("/tmp/file.yaml")
+// if err != nil {
+// panic(err)
+// }
+//}
+//
+//func (s *S) BenchmarkUnmarshal(c *C) {
+// var err error
+// for i := 0; i < c.N; i++ {
+// var v map[string]interface{}
+// err = yaml.Unmarshal(data, &v)
+// }
+// if err != nil {
+// panic(err)
+// }
+//}
+//
+//func (s *S) BenchmarkMarshal(c *C) {
+// var v map[string]interface{}
+// yaml.Unmarshal(data, &v)
+// c.ResetTimer()
+// for i := 0; i < c.N; i++ {
+// yaml.Marshal(&v)
+// }
+//}
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/emitterc.go b/kyaml/internal/forked/github.com/go-yaml/yaml/emitterc.go
new file mode 100644
index 000000000..f0f3d1867
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/emitterc.go
@@ -0,0 +1,2028 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+// Copyright (c) 2006-2010 Kirill Simonov
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+// of the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+package yaml
+
+import (
+ "bytes"
+ "fmt"
+)
+
+// Flush the buffer if needed.
+func flush(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) {
+ return yaml_emitter_flush(emitter)
+ }
+ return true
+}
+
+// Put a character to the output buffer.
+func put(emitter *yaml_emitter_t, value byte) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.buffer[emitter.buffer_pos] = value
+ emitter.buffer_pos++
+ emitter.column++
+ return true
+}
+
+// Put a line break to the output buffer.
+func put_break(emitter *yaml_emitter_t) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ switch emitter.line_break {
+ case yaml_CR_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\r'
+ emitter.buffer_pos += 1
+ case yaml_LN_BREAK:
+ emitter.buffer[emitter.buffer_pos] = '\n'
+ emitter.buffer_pos += 1
+ case yaml_CRLN_BREAK:
+ emitter.buffer[emitter.buffer_pos+0] = '\r'
+ emitter.buffer[emitter.buffer_pos+1] = '\n'
+ emitter.buffer_pos += 2
+ default:
+ panic("unknown line break setting")
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and below and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ return true
+}
+
+// Copy a character from a string into buffer.
+func write(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if emitter.buffer_pos+5 >= len(emitter.buffer) && !yaml_emitter_flush(emitter) {
+ return false
+ }
+ p := emitter.buffer_pos
+ w := width(s[*i])
+ switch w {
+ case 4:
+ emitter.buffer[p+3] = s[*i+3]
+ fallthrough
+ case 3:
+ emitter.buffer[p+2] = s[*i+2]
+ fallthrough
+ case 2:
+ emitter.buffer[p+1] = s[*i+1]
+ fallthrough
+ case 1:
+ emitter.buffer[p+0] = s[*i+0]
+ default:
+ panic("unknown character width")
+ }
+ emitter.column++
+ emitter.buffer_pos += w
+ *i += w
+ return true
+}
+
+// Write a whole string into buffer.
+func write_all(emitter *yaml_emitter_t, s []byte) bool {
+ for i := 0; i < len(s); {
+ if !write(emitter, s, &i) {
+ return false
+ }
+ }
+ return true
+}
+
+// Copy a line break character from a string into buffer.
+func write_break(emitter *yaml_emitter_t, s []byte, i *int) bool {
+ if s[*i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ *i++
+ } else {
+ if !write(emitter, s, i) {
+ return false
+ }
+ if emitter.column == 0 {
+ emitter.space_above = true
+ }
+ emitter.column = 0
+ emitter.line++
+ // [Go] Do this here and above and drop from everywhere else (see commented lines).
+ emitter.indention = true
+ }
+ return true
+}
+
+// Set an emitter error and return false.
+func yaml_emitter_set_emitter_error(emitter *yaml_emitter_t, problem string) bool {
+ emitter.error = yaml_EMITTER_ERROR
+ emitter.problem = problem
+ return false
+}
+
+// Emit an event.
+func yaml_emitter_emit(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.events = append(emitter.events, *event)
+ for !yaml_emitter_need_more_events(emitter) {
+ event := &emitter.events[emitter.events_head]
+ if !yaml_emitter_analyze_event(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_state_machine(emitter, event) {
+ return false
+ }
+ yaml_event_delete(event)
+ emitter.events_head++
+ }
+ return true
+}
+
+// Check if we need to accumulate more events before emitting.
+//
+// We accumulate extra
+// - 1 event for DOCUMENT-START
+// - 2 events for SEQUENCE-START
+// - 3 events for MAPPING-START
+//
+func yaml_emitter_need_more_events(emitter *yaml_emitter_t) bool {
+ if emitter.events_head == len(emitter.events) {
+ return true
+ }
+ var accumulate int
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_DOCUMENT_START_EVENT:
+ accumulate = 1
+ break
+ case yaml_SEQUENCE_START_EVENT:
+ accumulate = 2
+ break
+ case yaml_MAPPING_START_EVENT:
+ accumulate = 3
+ break
+ default:
+ return false
+ }
+ if len(emitter.events)-emitter.events_head > accumulate {
+ return false
+ }
+ var level int
+ for i := emitter.events_head; i < len(emitter.events); i++ {
+ switch emitter.events[i].typ {
+ case yaml_STREAM_START_EVENT, yaml_DOCUMENT_START_EVENT, yaml_SEQUENCE_START_EVENT, yaml_MAPPING_START_EVENT:
+ level++
+ case yaml_STREAM_END_EVENT, yaml_DOCUMENT_END_EVENT, yaml_SEQUENCE_END_EVENT, yaml_MAPPING_END_EVENT:
+ level--
+ }
+ if level == 0 {
+ return false
+ }
+ }
+ return true
+}
+
+// Append a directive to the directives stack.
+func yaml_emitter_append_tag_directive(emitter *yaml_emitter_t, value *yaml_tag_directive_t, allow_duplicates bool) bool {
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ if bytes.Equal(value.handle, emitter.tag_directives[i].handle) {
+ if allow_duplicates {
+ return true
+ }
+ return yaml_emitter_set_emitter_error(emitter, "duplicate %TAG directive")
+ }
+ }
+
+ // [Go] Do we actually need to copy this given garbage collection
+ // and the lack of deallocating destructors?
+ tag_copy := yaml_tag_directive_t{
+ handle: make([]byte, len(value.handle)),
+ prefix: make([]byte, len(value.prefix)),
+ }
+ copy(tag_copy.handle, value.handle)
+ copy(tag_copy.prefix, value.prefix)
+ emitter.tag_directives = append(emitter.tag_directives, tag_copy)
+ return true
+}
+
+// Increase the indentation level.
+func yaml_emitter_increase_indent(emitter *yaml_emitter_t, flow, indentless bool, compact_seq bool) bool {
+ emitter.indents = append(emitter.indents, emitter.indent)
+ if emitter.indent < 0 {
+ if flow {
+ emitter.indent = emitter.best_indent
+ } else {
+ emitter.indent = 0
+ }
+ } else if !indentless {
+ // [Go] This was changed so that indentations are more regular.
+ if emitter.states[len(emitter.states)-1] == yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE {
+ // The first indent inside a sequence will just skip the "- " indicator.
+ emitter.indent += 2
+ } else {
+ // Everything else aligns to the chosen indentation.
+ emitter.indent = emitter.best_indent*((emitter.indent+emitter.best_indent)/emitter.best_indent)
+ }
+ if compact_seq {
+ emitter.indent = emitter.indent - 2
+ }
+ }
+ return true
+}
+
+// State dispatcher.
+func yaml_emitter_state_machine(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ switch emitter.state {
+ default:
+ case yaml_EMIT_STREAM_START_STATE:
+ return yaml_emitter_emit_stream_start(emitter, event)
+
+ case yaml_EMIT_FIRST_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, true)
+
+ case yaml_EMIT_DOCUMENT_START_STATE:
+ return yaml_emitter_emit_document_start(emitter, event, false)
+
+ case yaml_EMIT_DOCUMENT_CONTENT_STATE:
+ return yaml_emitter_emit_document_content(emitter, event)
+
+ case yaml_EMIT_DOCUMENT_END_STATE:
+ return yaml_emitter_emit_document_end(emitter, event)
+
+ case yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, true)
+
+ case yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_flow_sequence_item(emitter, event, false, false)
+
+ case yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, true, false)
+
+ case yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, true)
+
+ case yaml_EMIT_FLOW_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_flow_mapping_key(emitter, event, false, false)
+
+ case yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_FLOW_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_flow_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE:
+ return yaml_emitter_emit_block_sequence_item(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_KEY_STATE:
+ return yaml_emitter_emit_block_mapping_key(emitter, event, false)
+
+ case yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, true)
+
+ case yaml_EMIT_BLOCK_MAPPING_VALUE_STATE:
+ return yaml_emitter_emit_block_mapping_value(emitter, event, false)
+
+ case yaml_EMIT_END_STATE:
+ return yaml_emitter_set_emitter_error(emitter, "expected nothing after STREAM-END")
+ }
+ panic("invalid emitter state")
+}
+
+// Expect STREAM-START.
+func yaml_emitter_emit_stream_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_STREAM_START_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected STREAM-START")
+ }
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = event.encoding
+ if emitter.encoding == yaml_ANY_ENCODING {
+ emitter.encoding = yaml_UTF8_ENCODING
+ }
+ }
+ if emitter.best_indent < 2 || emitter.best_indent > 9 {
+ emitter.best_indent = 2
+ }
+ if emitter.best_width >= 0 && emitter.best_width <= emitter.best_indent*2 {
+ emitter.best_width = 80
+ }
+ if emitter.best_width < 0 {
+ emitter.best_width = 1<<31 - 1
+ }
+ if emitter.line_break == yaml_ANY_BREAK {
+ emitter.line_break = yaml_LN_BREAK
+ }
+
+ emitter.indent = -1
+ emitter.line = 0
+ emitter.column = 0
+ emitter.whitespace = true
+ emitter.indention = true
+ emitter.space_above = true
+ emitter.foot_indent = -1
+
+ if emitter.encoding != yaml_UTF8_ENCODING {
+ if !yaml_emitter_write_bom(emitter) {
+ return false
+ }
+ }
+ emitter.state = yaml_EMIT_FIRST_DOCUMENT_START_STATE
+ return true
+}
+
+// Expect DOCUMENT-START or STREAM-END.
+func yaml_emitter_emit_document_start(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+
+ if event.typ == yaml_DOCUMENT_START_EVENT {
+
+ if event.version_directive != nil {
+ if !yaml_emitter_analyze_version_directive(emitter, event.version_directive) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_analyze_tag_directive(emitter, tag_directive) {
+ return false
+ }
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, false) {
+ return false
+ }
+ }
+
+ for i := 0; i < len(default_tag_directives); i++ {
+ tag_directive := &default_tag_directives[i]
+ if !yaml_emitter_append_tag_directive(emitter, tag_directive, true) {
+ return false
+ }
+ }
+
+ implicit := event.implicit
+ if !first || emitter.canonical {
+ implicit = false
+ }
+
+ if emitter.open_ended && (event.version_directive != nil || len(event.tag_directives) > 0) {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if event.version_directive != nil {
+ implicit = false
+ if !yaml_emitter_write_indicator(emitter, []byte("%YAML"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("1.1"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if len(event.tag_directives) > 0 {
+ implicit = false
+ for i := 0; i < len(event.tag_directives); i++ {
+ tag_directive := &event.tag_directives[i]
+ if !yaml_emitter_write_indicator(emitter, []byte("%TAG"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_handle(emitter, tag_directive.handle) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, tag_directive.prefix, true) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if yaml_emitter_check_empty_document(emitter) {
+ implicit = false
+ }
+ if !implicit {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte("---"), true, false, false) {
+ return false
+ }
+ if emitter.canonical || true {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ }
+
+ if len(emitter.head_comment) > 0 {
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !put_break(emitter) {
+ return false
+ }
+ }
+
+ emitter.state = yaml_EMIT_DOCUMENT_CONTENT_STATE
+ return true
+ }
+
+ if event.typ == yaml_STREAM_END_EVENT {
+ if emitter.open_ended {
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_END_STATE
+ return true
+ }
+
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-START or STREAM-END")
+}
+
+// Expect the root node.
+func yaml_emitter_emit_document_content(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ emitter.states = append(emitter.states, yaml_EMIT_DOCUMENT_END_STATE)
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_emit_node(emitter, event, true, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect DOCUMENT-END.
+func yaml_emitter_emit_document_end(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if event.typ != yaml_DOCUMENT_END_EVENT {
+ return yaml_emitter_set_emitter_error(emitter, "expected DOCUMENT-END")
+ }
+ // [Go] Force document foot separation.
+ emitter.foot_indent = 0
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.foot_indent = -1
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !event.implicit {
+ // [Go] Allocate the slice elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("..."), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_flush(emitter) {
+ return false
+ }
+ emitter.state = yaml_EMIT_DOCUMENT_START_STATE
+ emitter.tag_directives = emitter.tag_directives[:0]
+ return true
+}
+
+// Expect a flow item node.
+func yaml_emitter_emit_flow_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'['}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ if emitter.canonical && !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.column == 0 || emitter.canonical && !first {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{']'}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+
+ return true
+ }
+
+ if !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_TRAIL_ITEM_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_SEQUENCE_ITEM_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a flow key node.
+func yaml_emitter_emit_flow_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first, trail bool) bool {
+ if first {
+ if !yaml_emitter_write_indicator(emitter, []byte{'{'}, true, true, false) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false, false) {
+ return false
+ }
+ emitter.flow_level++
+ }
+
+ if event.typ == yaml_MAPPING_END_EVENT {
+ if (emitter.canonical || len(emitter.head_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0) && !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ emitter.flow_level--
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ if emitter.canonical && !first {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'}'}, false, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+
+ if !first && !trail {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+
+ if emitter.column == 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+
+ if !emitter.canonical && yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, false) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a flow value node.
+func yaml_emitter_emit_flow_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if emitter.canonical || emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, false) {
+ return false
+ }
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_TRAIL_KEY_STATE)
+ } else {
+ emitter.states = append(emitter.states, yaml_EMIT_FLOW_MAPPING_KEY_STATE)
+ }
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if len(emitter.line_comment)+len(emitter.foot_comment)+len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indicator(emitter, []byte{','}, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a block item node.
+func yaml_emitter_emit_block_sequence_item(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ seq := emitter.mapping_context && (emitter.column == 0 || !emitter.indention) &&
+ emitter.compact_sequence_indent
+ if !yaml_emitter_increase_indent(emitter, false, false, seq){
+ return false
+ }
+ }
+ if event.typ == yaml_SEQUENCE_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'-'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_SEQUENCE_ITEM_STATE)
+ if !yaml_emitter_emit_node(emitter, event, false, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+// Expect a block key node.
+func yaml_emitter_emit_block_mapping_key(emitter *yaml_emitter_t, event *yaml_event_t, first bool) bool {
+ if first {
+ if !yaml_emitter_increase_indent(emitter, false, false, false) {
+ return false
+ }
+ }
+ if !yaml_emitter_process_head_comment(emitter) {
+ return false
+ }
+ if event.typ == yaml_MAPPING_END_EVENT {
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if len(emitter.line_comment) > 0 {
+ // [Go] A line comment was provided for the key. That's unusual as the
+ // scanner associates line comments with the value. Either way,
+ // save the line comment and render it appropriately later.
+ emitter.key_line_comment = emitter.line_comment
+ emitter.line_comment = nil
+ }
+ if yaml_emitter_check_simple_key(emitter) {
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_SIMPLE_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, true)
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'?'}, true, false, true) {
+ return false
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_VALUE_STATE)
+ return yaml_emitter_emit_node(emitter, event, false, false, true, false)
+}
+
+// Expect a block value node.
+func yaml_emitter_emit_block_mapping_value(emitter *yaml_emitter_t, event *yaml_event_t, simple bool) bool {
+ if simple {
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, false, false, false) {
+ return false
+ }
+ } else {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{':'}, true, false, true) {
+ return false
+ }
+ }
+ if len(emitter.key_line_comment) > 0 {
+ // [Go] Line comments are generally associated with the value, but when there's
+ // no value on the same line as a mapping key they end up attached to the
+ // key itself.
+ if event.typ == yaml_SCALAR_EVENT {
+ if len(emitter.line_comment) == 0 {
+ // A scalar is coming and it has no line comments by itself yet,
+ // so just let it handle the line comment as usual. If it has a
+ // line comment, we can't have both so the one from the key is lost.
+ emitter.line_comment = emitter.key_line_comment
+ emitter.key_line_comment = nil
+ }
+ } else if event.sequence_style() != yaml_FLOW_SEQUENCE_STYLE && (event.typ == yaml_MAPPING_START_EVENT || event.typ == yaml_SEQUENCE_START_EVENT) {
+ // An indented block follows, so write the comment right now.
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ emitter.line_comment, emitter.key_line_comment = emitter.key_line_comment, emitter.line_comment
+ }
+ }
+ emitter.states = append(emitter.states, yaml_EMIT_BLOCK_MAPPING_KEY_STATE)
+ if !yaml_emitter_emit_node(emitter, event, false, false, true, false) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter, false) {
+ return false
+ }
+ if !yaml_emitter_process_foot_comment(emitter) {
+ return false
+ }
+ return true
+}
+
+func yaml_emitter_silent_nil_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ return event.typ == yaml_SCALAR_EVENT && event.implicit && !emitter.canonical && len(emitter.scalar_data.value) == 0
+}
+
+// Expect a node.
+func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
+ root bool, sequence bool, mapping bool, simple_key bool) bool {
+
+ emitter.root_context = root
+ emitter.sequence_context = sequence
+ emitter.mapping_context = mapping
+ emitter.simple_key_context = simple_key
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ return yaml_emitter_emit_alias(emitter, event)
+ case yaml_SCALAR_EVENT:
+ return yaml_emitter_emit_scalar(emitter, event)
+ case yaml_SEQUENCE_START_EVENT:
+ return yaml_emitter_emit_sequence_start(emitter, event)
+ case yaml_MAPPING_START_EVENT:
+ return yaml_emitter_emit_mapping_start(emitter, event)
+ default:
+ return yaml_emitter_set_emitter_error(emitter,
+ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
+ }
+}
+
+// Expect ALIAS.
+func yaml_emitter_emit_alias(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SCALAR.
+func yaml_emitter_emit_scalar(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_select_scalar_style(emitter, event) {
+ return false
+ }
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if !yaml_emitter_increase_indent(emitter, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_process_scalar(emitter) {
+ return false
+ }
+ emitter.indent = emitter.indents[len(emitter.indents)-1]
+ emitter.indents = emitter.indents[:len(emitter.indents)-1]
+ emitter.state = emitter.states[len(emitter.states)-1]
+ emitter.states = emitter.states[:len(emitter.states)-1]
+ return true
+}
+
+// Expect SEQUENCE-START.
+func yaml_emitter_emit_sequence_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.sequence_style() == yaml_FLOW_SEQUENCE_STYLE ||
+ yaml_emitter_check_empty_sequence(emitter) {
+ emitter.state = yaml_EMIT_FLOW_SEQUENCE_FIRST_ITEM_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_SEQUENCE_FIRST_ITEM_STATE
+ }
+ return true
+}
+
+// Expect MAPPING-START.
+func yaml_emitter_emit_mapping_start(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+ if !yaml_emitter_process_anchor(emitter) {
+ return false
+ }
+ if !yaml_emitter_process_tag(emitter) {
+ return false
+ }
+ if emitter.flow_level > 0 || emitter.canonical || event.mapping_style() == yaml_FLOW_MAPPING_STYLE ||
+ yaml_emitter_check_empty_mapping(emitter) {
+ emitter.state = yaml_EMIT_FLOW_MAPPING_FIRST_KEY_STATE
+ } else {
+ emitter.state = yaml_EMIT_BLOCK_MAPPING_FIRST_KEY_STATE
+ }
+ return true
+}
+
+// Check if the document content is an empty scalar.
+func yaml_emitter_check_empty_document(emitter *yaml_emitter_t) bool {
+ return false // [Go] Huh?
+}
+
+// Check if the next events represent an empty sequence.
+func yaml_emitter_check_empty_sequence(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_SEQUENCE_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_SEQUENCE_END_EVENT
+}
+
+// Check if the next events represent an empty mapping.
+func yaml_emitter_check_empty_mapping(emitter *yaml_emitter_t) bool {
+ if len(emitter.events)-emitter.events_head < 2 {
+ return false
+ }
+ return emitter.events[emitter.events_head].typ == yaml_MAPPING_START_EVENT &&
+ emitter.events[emitter.events_head+1].typ == yaml_MAPPING_END_EVENT
+}
+
+// Check if the next node can be expressed as a simple key.
+func yaml_emitter_check_simple_key(emitter *yaml_emitter_t) bool {
+ length := 0
+ switch emitter.events[emitter.events_head].typ {
+ case yaml_ALIAS_EVENT:
+ length += len(emitter.anchor_data.anchor)
+ case yaml_SCALAR_EVENT:
+ if emitter.scalar_data.multiline {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix) +
+ len(emitter.scalar_data.value)
+ case yaml_SEQUENCE_START_EVENT:
+ if !yaml_emitter_check_empty_sequence(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ case yaml_MAPPING_START_EVENT:
+ if !yaml_emitter_check_empty_mapping(emitter) {
+ return false
+ }
+ length += len(emitter.anchor_data.anchor) +
+ len(emitter.tag_data.handle) +
+ len(emitter.tag_data.suffix)
+ default:
+ return false
+ }
+ return length <= 128
+}
+
+// Determine an acceptable scalar style.
+func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ no_tag := len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0
+ if no_tag && !event.implicit && !event.quoted_implicit {
+ return yaml_emitter_set_emitter_error(emitter, "neither tag nor implicit flags are specified")
+ }
+
+ style := event.scalar_style()
+ if style == yaml_ANY_SCALAR_STYLE {
+ style = yaml_PLAIN_SCALAR_STYLE
+ }
+ if emitter.canonical {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ if emitter.simple_key_context && emitter.scalar_data.multiline {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ if style == yaml_PLAIN_SCALAR_STYLE {
+ if emitter.flow_level > 0 && !emitter.scalar_data.flow_plain_allowed ||
+ emitter.flow_level == 0 && !emitter.scalar_data.block_plain_allowed {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if len(emitter.scalar_data.value) == 0 && (emitter.flow_level > 0 || emitter.simple_key_context) {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ if no_tag && !event.implicit {
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_SINGLE_QUOTED_SCALAR_STYLE {
+ if !emitter.scalar_data.single_quoted_allowed {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+ if style == yaml_LITERAL_SCALAR_STYLE || style == yaml_FOLDED_SCALAR_STYLE {
+ if !emitter.scalar_data.block_allowed || emitter.flow_level > 0 || emitter.simple_key_context {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ }
+
+ if no_tag && !event.quoted_implicit && style != yaml_PLAIN_SCALAR_STYLE {
+ emitter.tag_data.handle = []byte{'!'}
+ }
+ emitter.scalar_data.style = style
+ return true
+}
+
+// Write an anchor.
+func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
+ if emitter.anchor_data.anchor == nil {
+ return true
+ }
+ c := []byte{'&'}
+ if emitter.anchor_data.alias {
+ c[0] = '*'
+ }
+ if !yaml_emitter_write_indicator(emitter, c, true, false, false) {
+ return false
+ }
+ return yaml_emitter_write_anchor(emitter, emitter.anchor_data.anchor)
+}
+
+// Write a tag.
+func yaml_emitter_process_tag(emitter *yaml_emitter_t) bool {
+ if len(emitter.tag_data.handle) == 0 && len(emitter.tag_data.suffix) == 0 {
+ return true
+ }
+ if len(emitter.tag_data.handle) > 0 {
+ if !yaml_emitter_write_tag_handle(emitter, emitter.tag_data.handle) {
+ return false
+ }
+ if len(emitter.tag_data.suffix) > 0 {
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ }
+ } else {
+ // [Go] Allocate these slices elsewhere.
+ if !yaml_emitter_write_indicator(emitter, []byte("!<"), true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_tag_content(emitter, emitter.tag_data.suffix, false) {
+ return false
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+// Write a scalar.
+func yaml_emitter_process_scalar(emitter *yaml_emitter_t) bool {
+ switch emitter.scalar_data.style {
+ case yaml_PLAIN_SCALAR_STYLE:
+ return yaml_emitter_write_plain_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_SINGLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_single_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_DOUBLE_QUOTED_SCALAR_STYLE:
+ return yaml_emitter_write_double_quoted_scalar(emitter, emitter.scalar_data.value, !emitter.simple_key_context)
+
+ case yaml_LITERAL_SCALAR_STYLE:
+ return yaml_emitter_write_literal_scalar(emitter, emitter.scalar_data.value)
+
+ case yaml_FOLDED_SCALAR_STYLE:
+ return yaml_emitter_write_folded_scalar(emitter, emitter.scalar_data.value)
+ }
+ panic("unknown scalar style")
+}
+
+// Write a head comment.
+func yaml_emitter_process_head_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.tail_comment) > 0 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.tail_comment) {
+ return false
+ }
+ emitter.tail_comment = emitter.tail_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ }
+
+ if len(emitter.head_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.head_comment) {
+ return false
+ }
+ emitter.head_comment = emitter.head_comment[:0]
+ return true
+}
+
+// Write an line comment.
+func yaml_emitter_process_line_comment(emitter *yaml_emitter_t, linebreak bool) bool {
+ if len(emitter.line_comment) == 0 {
+ if linebreak && !put_break(emitter) {
+ return false
+ }
+ return true
+ }
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.line_comment) {
+ return false
+ }
+ emitter.line_comment = emitter.line_comment[:0]
+ return true
+}
+
+// Write a foot comment.
+func yaml_emitter_process_foot_comment(emitter *yaml_emitter_t) bool {
+ if len(emitter.foot_comment) == 0 {
+ return true
+ }
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !yaml_emitter_write_comment(emitter, emitter.foot_comment) {
+ return false
+ }
+ emitter.foot_comment = emitter.foot_comment[:0]
+ emitter.foot_indent = emitter.indent
+ if emitter.foot_indent < 0 {
+ emitter.foot_indent = 0
+ }
+ return true
+}
+
+// Check if a %YAML directive is valid.
+func yaml_emitter_analyze_version_directive(emitter *yaml_emitter_t, version_directive *yaml_version_directive_t) bool {
+ if version_directive.major != 1 || version_directive.minor != 1 {
+ return yaml_emitter_set_emitter_error(emitter, "incompatible %YAML directive")
+ }
+ return true
+}
+
+// Check if a %TAG directive is valid.
+func yaml_emitter_analyze_tag_directive(emitter *yaml_emitter_t, tag_directive *yaml_tag_directive_t) bool {
+ handle := tag_directive.handle
+ prefix := tag_directive.prefix
+ if len(handle) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must not be empty")
+ }
+ if handle[0] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must start with '!'")
+ }
+ if handle[len(handle)-1] != '!' {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must end with '!'")
+ }
+ for i := 1; i < len(handle)-1; i += width(handle[i]) {
+ if !is_alpha(handle, i) {
+ return yaml_emitter_set_emitter_error(emitter, "tag handle must contain alphanumerical characters only")
+ }
+ }
+ if len(prefix) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag prefix must not be empty")
+ }
+ return true
+}
+
+// Check if an anchor is valid.
+func yaml_emitter_analyze_anchor(emitter *yaml_emitter_t, anchor []byte, alias bool) bool {
+ if len(anchor) == 0 {
+ problem := "anchor value must not be empty"
+ if alias {
+ problem = "alias value must not be empty"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ for i := 0; i < len(anchor); i += width(anchor[i]) {
+ if !is_alpha(anchor, i) {
+ problem := "anchor value must contain alphanumerical characters only"
+ if alias {
+ problem = "alias value must contain alphanumerical characters only"
+ }
+ return yaml_emitter_set_emitter_error(emitter, problem)
+ }
+ }
+ emitter.anchor_data.anchor = anchor
+ emitter.anchor_data.alias = alias
+ return true
+}
+
+// Check if a tag is valid.
+func yaml_emitter_analyze_tag(emitter *yaml_emitter_t, tag []byte) bool {
+ if len(tag) == 0 {
+ return yaml_emitter_set_emitter_error(emitter, "tag value must not be empty")
+ }
+ for i := 0; i < len(emitter.tag_directives); i++ {
+ tag_directive := &emitter.tag_directives[i]
+ if bytes.HasPrefix(tag, tag_directive.prefix) {
+ emitter.tag_data.handle = tag_directive.handle
+ emitter.tag_data.suffix = tag[len(tag_directive.prefix):]
+ return true
+ }
+ }
+ emitter.tag_data.suffix = tag
+ return true
+}
+
+// Check if a scalar is valid.
+func yaml_emitter_analyze_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ var (
+ block_indicators = false
+ flow_indicators = false
+ line_breaks = false
+ special_characters = false
+ tab_characters = false
+
+ leading_space = false
+ leading_break = false
+ trailing_space = false
+ trailing_break = false
+ break_space = false
+ space_break = false
+
+ preceded_by_whitespace = false
+ followed_by_whitespace = false
+ previous_space = false
+ previous_break = false
+ )
+
+ emitter.scalar_data.value = value
+
+ if len(value) == 0 {
+ emitter.scalar_data.multiline = false
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = false
+ return true
+ }
+
+ if len(value) >= 3 && ((value[0] == '-' && value[1] == '-' && value[2] == '-') || (value[0] == '.' && value[1] == '.' && value[2] == '.')) {
+ block_indicators = true
+ flow_indicators = true
+ }
+
+ preceded_by_whitespace = true
+ for i, w := 0, 0; i < len(value); i += w {
+ w = width(value[i])
+ followed_by_whitespace = i+w >= len(value) || is_blank(value, i+w)
+
+ if i == 0 {
+ switch value[i] {
+ case '#', ',', '[', ']', '{', '}', '&', '*', '!', '|', '>', '\'', '"', '%', '@', '`':
+ flow_indicators = true
+ block_indicators = true
+ case '?', ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '-':
+ if followed_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ } else {
+ switch value[i] {
+ case ',', '?', '[', ']', '{', '}':
+ flow_indicators = true
+ case ':':
+ flow_indicators = true
+ if followed_by_whitespace {
+ block_indicators = true
+ }
+ case '#':
+ if preceded_by_whitespace {
+ flow_indicators = true
+ block_indicators = true
+ }
+ }
+ }
+
+ if value[i] == '\t' {
+ tab_characters = true
+ } else if !is_printable(value, i) || !is_ascii(value, i) && !emitter.unicode {
+ special_characters = true
+ }
+ if is_space(value, i) {
+ if i == 0 {
+ leading_space = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_space = true
+ }
+ if previous_break {
+ break_space = true
+ }
+ previous_space = true
+ previous_break = false
+ } else if is_break(value, i) {
+ line_breaks = true
+ if i == 0 {
+ leading_break = true
+ }
+ if i+width(value[i]) == len(value) {
+ trailing_break = true
+ }
+ if previous_space {
+ space_break = true
+ }
+ previous_space = false
+ previous_break = true
+ } else {
+ previous_space = false
+ previous_break = false
+ }
+
+ // [Go]: Why 'z'? Couldn't be the end of the string as that's the loop condition.
+ preceded_by_whitespace = is_blankz(value, i)
+ }
+
+ emitter.scalar_data.multiline = line_breaks
+ emitter.scalar_data.flow_plain_allowed = true
+ emitter.scalar_data.block_plain_allowed = true
+ emitter.scalar_data.single_quoted_allowed = true
+ emitter.scalar_data.block_allowed = true
+
+ if leading_space || leading_break || trailing_space || trailing_break {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if trailing_space {
+ emitter.scalar_data.block_allowed = false
+ }
+ if break_space {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || tab_characters || special_characters {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ emitter.scalar_data.single_quoted_allowed = false
+ }
+ if space_break || special_characters {
+ emitter.scalar_data.block_allowed = false
+ }
+ if line_breaks {
+ emitter.scalar_data.flow_plain_allowed = false
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ if flow_indicators {
+ emitter.scalar_data.flow_plain_allowed = false
+ }
+ if block_indicators {
+ emitter.scalar_data.block_plain_allowed = false
+ }
+ return true
+}
+
+// Check if the event data is valid.
+func yaml_emitter_analyze_event(emitter *yaml_emitter_t, event *yaml_event_t) bool {
+
+ emitter.anchor_data.anchor = nil
+ emitter.tag_data.handle = nil
+ emitter.tag_data.suffix = nil
+ emitter.scalar_data.value = nil
+
+ if len(event.head_comment) > 0 {
+ emitter.head_comment = event.head_comment
+ }
+ if len(event.line_comment) > 0 {
+ emitter.line_comment = event.line_comment
+ }
+ if len(event.foot_comment) > 0 {
+ emitter.foot_comment = event.foot_comment
+ }
+ if len(event.tail_comment) > 0 {
+ emitter.tail_comment = event.tail_comment
+ }
+
+ switch event.typ {
+ case yaml_ALIAS_EVENT:
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, true) {
+ return false
+ }
+
+ case yaml_SCALAR_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || (!event.implicit && !event.quoted_implicit)) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ if !yaml_emitter_analyze_scalar(emitter, event.value) {
+ return false
+ }
+
+ case yaml_SEQUENCE_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+
+ case yaml_MAPPING_START_EVENT:
+ if len(event.anchor) > 0 {
+ if !yaml_emitter_analyze_anchor(emitter, event.anchor, false) {
+ return false
+ }
+ }
+ if len(event.tag) > 0 && (emitter.canonical || !event.implicit) {
+ if !yaml_emitter_analyze_tag(emitter, event.tag) {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+// Write the BOM character.
+func yaml_emitter_write_bom(emitter *yaml_emitter_t) bool {
+ if !flush(emitter) {
+ return false
+ }
+ pos := emitter.buffer_pos
+ emitter.buffer[pos+0] = '\xEF'
+ emitter.buffer[pos+1] = '\xBB'
+ emitter.buffer[pos+2] = '\xBF'
+ emitter.buffer_pos += 3
+ return true
+}
+
+func yaml_emitter_write_indent(emitter *yaml_emitter_t) bool {
+ indent := emitter.indent
+ if indent < 0 {
+ indent = 0
+ }
+ if !emitter.indention || emitter.column > indent || (emitter.column == indent && !emitter.whitespace) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if emitter.foot_indent == indent {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ for emitter.column < indent {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ emitter.whitespace = true
+ //emitter.indention = true
+ emitter.space_above = false
+ emitter.foot_indent = -1
+ return true
+}
+
+func yaml_emitter_write_indicator(emitter *yaml_emitter_t, indicator []byte, need_whitespace, is_whitespace, is_indention bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, indicator) {
+ return false
+ }
+ emitter.whitespace = is_whitespace
+ emitter.indention = (emitter.indention && is_indention)
+ emitter.open_ended = false
+ return true
+}
+
+func yaml_emitter_write_anchor(emitter *yaml_emitter_t, value []byte) bool {
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_handle(emitter *yaml_emitter_t, value []byte) bool {
+ if !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ if !write_all(emitter, value) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_tag_content(emitter *yaml_emitter_t, value []byte, need_whitespace bool) bool {
+ if need_whitespace && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+ for i := 0; i < len(value); {
+ var must_write bool
+ switch value[i] {
+ case ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '_', '.', '~', '*', '\'', '(', ')', '[', ']':
+ must_write = true
+ default:
+ must_write = is_alpha(value, i)
+ }
+ if must_write {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ } else {
+ w := width(value[i])
+ for k := 0; k < w; k++ {
+ octet := value[i]
+ i++
+ if !put(emitter, '%') {
+ return false
+ }
+
+ c := octet >> 4
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+
+ c = octet & 0x0f
+ if c < 10 {
+ c += '0'
+ } else {
+ c += 'A' - 10
+ }
+ if !put(emitter, c) {
+ return false
+ }
+ }
+ }
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_plain_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ if len(value) > 0 && !emitter.whitespace {
+ if !put(emitter, ' ') {
+ return false
+ }
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+
+ if len(value) > 0 {
+ emitter.whitespace = false
+ }
+ emitter.indention = false
+ if emitter.root_context {
+ emitter.open_ended = true
+ }
+
+ return true
+}
+
+func yaml_emitter_write_single_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, true, false, false) {
+ return false
+ }
+
+ spaces := false
+ breaks := false
+ for i := 0; i < len(value); {
+ if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 && !is_space(value, i+1) {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ spaces = true
+ } else if is_break(value, i) {
+ if !breaks && value[i] == '\n' {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if value[i] == '\'' {
+ if !put(emitter, '\'') {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ spaces = false
+ breaks = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'\''}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_double_quoted_scalar(emitter *yaml_emitter_t, value []byte, allow_breaks bool) bool {
+ spaces := false
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, true, false, false) {
+ return false
+ }
+
+ for i := 0; i < len(value); {
+ if !is_printable(value, i) || (!emitter.unicode && !is_ascii(value, i)) ||
+ is_bom(value, i) || is_break(value, i) ||
+ value[i] == '"' || value[i] == '\\' {
+
+ octet := value[i]
+
+ var w int
+ var v rune
+ switch {
+ case octet&0x80 == 0x00:
+ w, v = 1, rune(octet&0x7F)
+ case octet&0xE0 == 0xC0:
+ w, v = 2, rune(octet&0x1F)
+ case octet&0xF0 == 0xE0:
+ w, v = 3, rune(octet&0x0F)
+ case octet&0xF8 == 0xF0:
+ w, v = 4, rune(octet&0x07)
+ }
+ for k := 1; k < w; k++ {
+ octet = value[i+k]
+ v = (v << 6) + (rune(octet) & 0x3F)
+ }
+ i += w
+
+ if !put(emitter, '\\') {
+ return false
+ }
+
+ var ok bool
+ switch v {
+ case 0x00:
+ ok = put(emitter, '0')
+ case 0x07:
+ ok = put(emitter, 'a')
+ case 0x08:
+ ok = put(emitter, 'b')
+ case 0x09:
+ ok = put(emitter, 't')
+ case 0x0A:
+ ok = put(emitter, 'n')
+ case 0x0b:
+ ok = put(emitter, 'v')
+ case 0x0c:
+ ok = put(emitter, 'f')
+ case 0x0d:
+ ok = put(emitter, 'r')
+ case 0x1b:
+ ok = put(emitter, 'e')
+ case 0x22:
+ ok = put(emitter, '"')
+ case 0x5c:
+ ok = put(emitter, '\\')
+ case 0x85:
+ ok = put(emitter, 'N')
+ case 0xA0:
+ ok = put(emitter, '_')
+ case 0x2028:
+ ok = put(emitter, 'L')
+ case 0x2029:
+ ok = put(emitter, 'P')
+ default:
+ if v <= 0xFF {
+ ok = put(emitter, 'x')
+ w = 2
+ } else if v <= 0xFFFF {
+ ok = put(emitter, 'u')
+ w = 4
+ } else {
+ ok = put(emitter, 'U')
+ w = 8
+ }
+ for k := (w - 1) * 4; ok && k >= 0; k -= 4 {
+ digit := byte((v >> uint(k)) & 0x0F)
+ if digit < 10 {
+ ok = put(emitter, digit+'0')
+ } else {
+ ok = put(emitter, digit+'A'-10)
+ }
+ }
+ }
+ if !ok {
+ return false
+ }
+ spaces = false
+ } else if is_space(value, i) {
+ if allow_breaks && !spaces && emitter.column > emitter.best_width && i > 0 && i < len(value)-1 {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if is_space(value, i+1) {
+ if !put(emitter, '\\') {
+ return false
+ }
+ }
+ i += width(value[i])
+ } else if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = true
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ spaces = false
+ }
+ }
+ if !yaml_emitter_write_indicator(emitter, []byte{'"'}, false, false, false) {
+ return false
+ }
+ emitter.whitespace = false
+ emitter.indention = false
+ return true
+}
+
+func yaml_emitter_write_block_scalar_hints(emitter *yaml_emitter_t, value []byte) bool {
+ if is_space(value, 0) || is_break(value, 0) {
+ indent_hint := []byte{'0' + byte(emitter.best_indent)}
+ if !yaml_emitter_write_indicator(emitter, indent_hint, false, false, false) {
+ return false
+ }
+ }
+
+ emitter.open_ended = false
+
+ var chomp_hint [1]byte
+ if len(value) == 0 {
+ chomp_hint[0] = '-'
+ } else {
+ i := len(value) - 1
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if !is_break(value, i) {
+ chomp_hint[0] = '-'
+ } else if i == 0 {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ } else {
+ i--
+ for value[i]&0xC0 == 0x80 {
+ i--
+ }
+ if is_break(value, i) {
+ chomp_hint[0] = '+'
+ emitter.open_ended = true
+ }
+ }
+ }
+ if chomp_hint[0] != 0 {
+ if !yaml_emitter_write_indicator(emitter, chomp_hint[:], false, false, false) {
+ return false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_literal_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'|'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter, true) {
+ return false
+ }
+ //emitter.indention = true
+ emitter.whitespace = true
+ breaks := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ }
+ if !write(emitter, value, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+
+ return true
+}
+
+func yaml_emitter_write_folded_scalar(emitter *yaml_emitter_t, value []byte) bool {
+ if !yaml_emitter_write_indicator(emitter, []byte{'>'}, true, false, false) {
+ return false
+ }
+ if !yaml_emitter_write_block_scalar_hints(emitter, value) {
+ return false
+ }
+ if !yaml_emitter_process_line_comment(emitter, true) {
+ return false
+ }
+
+ //emitter.indention = true
+ emitter.whitespace = true
+
+ breaks := true
+ leading_spaces := true
+ for i := 0; i < len(value); {
+ if is_break(value, i) {
+ if !breaks && !leading_spaces && value[i] == '\n' {
+ k := 0
+ for is_break(value, k) {
+ k += width(value[k])
+ }
+ if !is_blankz(value, k) {
+ if !put_break(emitter) {
+ return false
+ }
+ }
+ }
+ if !write_break(emitter, value, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ } else {
+ if breaks {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ leading_spaces = is_blank(value, i)
+ }
+ if !breaks && is_space(value, i) && !is_space(value, i+1) && emitter.column > emitter.best_width {
+ if !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ i += width(value[i])
+ } else {
+ if !write(emitter, value, &i) {
+ return false
+ }
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ return true
+}
+
+func yaml_emitter_write_comment(emitter *yaml_emitter_t, comment []byte) bool {
+ breaks := false
+ pound := false
+ for i := 0; i < len(comment); {
+ if is_break(comment, i) {
+ if !write_break(emitter, comment, &i) {
+ return false
+ }
+ //emitter.indention = true
+ breaks = true
+ pound = false
+ } else {
+ if breaks && !yaml_emitter_write_indent(emitter) {
+ return false
+ }
+ if !pound {
+ if comment[i] != '#' && (!put(emitter, '#') || !put(emitter, ' ')) {
+ return false
+ }
+ pound = true
+ }
+ if !write(emitter, comment, &i) {
+ return false
+ }
+ emitter.indention = false
+ breaks = false
+ }
+ }
+ if !breaks && !put_break(emitter) {
+ return false
+ }
+
+ emitter.whitespace = true
+ //emitter.indention = true
+ return true
+}
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/encode.go b/kyaml/internal/forked/github.com/go-yaml/yaml/encode.go
new file mode 100644
index 000000000..de9e72a3e
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/encode.go
@@ -0,0 +1,577 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml
+
+import (
+ "encoding"
+ "fmt"
+ "io"
+ "reflect"
+ "regexp"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+type encoder struct {
+ emitter yaml_emitter_t
+ event yaml_event_t
+ out []byte
+ flow bool
+ indent int
+ doneInit bool
+}
+
+func newEncoder() *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_string(&e.emitter, &e.out)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func newEncoderWithWriter(w io.Writer) *encoder {
+ e := &encoder{}
+ yaml_emitter_initialize(&e.emitter)
+ yaml_emitter_set_output_writer(&e.emitter, w)
+ yaml_emitter_set_unicode(&e.emitter, true)
+ return e
+}
+
+func (e *encoder) init() {
+ if e.doneInit {
+ return
+ }
+ if e.indent == 0 {
+ e.indent = 4
+ }
+ e.emitter.best_indent = e.indent
+ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
+ e.emit()
+ e.doneInit = true
+}
+
+func (e *encoder) finish() {
+ e.emitter.open_ended = false
+ yaml_stream_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) destroy() {
+ yaml_emitter_delete(&e.emitter)
+}
+
+func (e *encoder) emit() {
+ // This will internally delete the e.event value.
+ e.must(yaml_emitter_emit(&e.emitter, &e.event))
+}
+
+func (e *encoder) must(ok bool) {
+ if !ok {
+ msg := e.emitter.problem
+ if msg == "" {
+ msg = "unknown problem generating YAML content"
+ }
+ failf("%s", msg)
+ }
+}
+
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+ e.init()
+ var node *Node
+ if in.IsValid() {
+ node, _ = in.Interface().(*Node)
+ }
+ if node != nil && node.Kind == DocumentNode {
+ e.nodev(in)
+ } else {
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.emit()
+ e.marshal(tag, in)
+ yaml_document_end_event_initialize(&e.event, true)
+ e.emit()
+ }
+}
+
+func (e *encoder) marshal(tag string, in reflect.Value) {
+ tag = shortTag(tag)
+ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
+ e.nilv()
+ return
+ }
+ iface := in.Interface()
+ switch value := iface.(type) {
+ case *Node:
+ e.nodev(in)
+ return
+ case Node:
+ if !in.CanAddr() {
+ var n = reflect.New(in.Type()).Elem()
+ n.Set(in)
+ in = n
+ }
+ e.nodev(in.Addr())
+ return
+ case time.Time:
+ e.timev(tag, in)
+ return
+ case *time.Time:
+ e.timev(tag, in.Elem())
+ return
+ case time.Duration:
+ e.stringv(tag, reflect.ValueOf(value.String()))
+ return
+ case Marshaler:
+ v, err := value.MarshalYAML()
+ if err != nil {
+ fail(err)
+ }
+ if v == nil {
+ e.nilv()
+ return
+ }
+ e.marshal(tag, reflect.ValueOf(v))
+ return
+ case encoding.TextMarshaler:
+ text, err := value.MarshalText()
+ if err != nil {
+ fail(err)
+ }
+ in = reflect.ValueOf(string(text))
+ case nil:
+ e.nilv()
+ return
+ }
+ switch in.Kind() {
+ case reflect.Interface:
+ e.marshal(tag, in.Elem())
+ case reflect.Map:
+ e.mapv(tag, in)
+ case reflect.Ptr:
+ e.marshal(tag, in.Elem())
+ case reflect.Struct:
+ e.structv(tag, in)
+ case reflect.Slice, reflect.Array:
+ e.slicev(tag, in)
+ case reflect.String:
+ e.stringv(tag, in)
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ e.intv(tag, in)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ e.uintv(tag, in)
+ case reflect.Float32, reflect.Float64:
+ e.floatv(tag, in)
+ case reflect.Bool:
+ e.boolv(tag, in)
+ default:
+ panic("cannot marshal type: " + in.Type().String())
+ }
+}
+
+func (e *encoder) mapv(tag string, in reflect.Value) {
+ e.mappingv(tag, func() {
+ keys := keyList(in.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ e.marshal("", k)
+ e.marshal("", in.MapIndex(k))
+ }
+ })
+}
+
+func (e *encoder) fieldByIndex(v reflect.Value, index []int) (field reflect.Value) {
+ for _, num := range index {
+ for {
+ if v.Kind() == reflect.Ptr {
+ if v.IsNil() {
+ return reflect.Value{}
+ }
+ v = v.Elem()
+ continue
+ }
+ break
+ }
+ v = v.Field(num)
+ }
+ return v
+}
+
+func (e *encoder) structv(tag string, in reflect.Value) {
+ sinfo, err := getStructInfo(in.Type())
+ if err != nil {
+ panic(err)
+ }
+ e.mappingv(tag, func() {
+ for _, info := range sinfo.FieldsList {
+ var value reflect.Value
+ if info.Inline == nil {
+ value = in.Field(info.Num)
+ } else {
+ value = e.fieldByIndex(in, info.Inline)
+ if !value.IsValid() {
+ continue
+ }
+ }
+ if info.OmitEmpty && isZero(value) {
+ continue
+ }
+ e.marshal("", reflect.ValueOf(info.Key))
+ e.flow = info.Flow
+ e.marshal("", value)
+ }
+ if sinfo.InlineMap >= 0 {
+ m := in.Field(sinfo.InlineMap)
+ if m.Len() > 0 {
+ e.flow = false
+ keys := keyList(m.MapKeys())
+ sort.Sort(keys)
+ for _, k := range keys {
+ if _, found := sinfo.FieldsMap[k.String()]; found {
+ panic(fmt.Sprintf("cannot have key %q in inlined map: conflicts with struct field", k.String()))
+ }
+ e.marshal("", k)
+ e.flow = false
+ e.marshal("", m.MapIndex(k))
+ }
+ }
+ }
+ })
+}
+
+func (e *encoder) mappingv(tag string, f func()) {
+ implicit := tag == ""
+ style := yaml_BLOCK_MAPPING_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
+ e.emit()
+ f()
+ yaml_mapping_end_event_initialize(&e.event)
+ e.emit()
+}
+
+func (e *encoder) slicev(tag string, in reflect.Value) {
+ implicit := tag == ""
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if e.flow {
+ e.flow = false
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+ e.emit()
+ n := in.Len()
+ for i := 0; i < n; i++ {
+ e.marshal("", in.Index(i))
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.emit()
+}
+
+// isBase60 returns whether s is in base 60 notation as defined in YAML 1.1.
+//
+// The base 60 float notation in YAML 1.1 is a terrible idea and is unsupported
+// in YAML 1.2 and by this package, but these should be marshalled quoted for
+// the time being for compatibility with other parsers.
+func isBase60Float(s string) (result bool) {
+ // Fast path.
+ if s == "" {
+ return false
+ }
+ c := s[0]
+ if !(c == '+' || c == '-' || c >= '0' && c <= '9') || strings.IndexByte(s, ':') < 0 {
+ return false
+ }
+ // Do the full match.
+ return base60float.MatchString(s)
+}
+
+// From http://yaml.org/type/float.html, except the regular expression there
+// is bogus. In practice parsers do not enforce the "\.[0-9_]*" suffix.
+var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0-9_]*)?$`)
+
+// isOldBool returns whether s is bool notation as defined in YAML 1.1.
+//
+// We continue to force strings that YAML 1.1 would interpret as booleans to be
+// rendered as quotes strings so that the marshalled output valid for YAML 1.1
+// parsing.
+func isOldBool(s string) (result bool) {
+ switch s {
+ case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON",
+ "n", "N", "no", "No", "NO", "off", "Off", "OFF":
+ return true
+ default:
+ return false
+ }
+}
+
+func (e *encoder) stringv(tag string, in reflect.Value) {
+ var style yaml_scalar_style_t
+ s := in.String()
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if tag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", shortTag(tag))
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ s = encodeBase64(s)
+ case tag == "":
+ // Check to see if it would resolve to a specific
+ // tag when encoded unquoted. If it doesn't,
+ // there's no need to quote it.
+ rtag, _ := resolve("", s)
+ canUsePlain = rtag == strTag && !(isBase60Float(s) || isOldBool(s))
+ }
+ // Note: it's possible for user code to emit invalid YAML
+ // if they explicitly specify a tag and a string containing
+ // text that's incompatible with that tag.
+ switch {
+ case strings.Contains(s, "\n"):
+ if e.flow {
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ } else {
+ style = yaml_LITERAL_SCALAR_STYLE
+ }
+ case canUsePlain:
+ style = yaml_PLAIN_SCALAR_STYLE
+ default:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+ e.emitScalar(s, "", tag, style, nil, nil, nil, nil)
+}
+
+func (e *encoder) boolv(tag string, in reflect.Value) {
+ var s string
+ if in.Bool() {
+ s = "true"
+ } else {
+ s = "false"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) intv(tag string, in reflect.Value) {
+ s := strconv.FormatInt(in.Int(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) uintv(tag string, in reflect.Value) {
+ s := strconv.FormatUint(in.Uint(), 10)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) timev(tag string, in reflect.Value) {
+ t := in.Interface().(time.Time)
+ s := t.Format(time.RFC3339Nano)
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) floatv(tag string, in reflect.Value) {
+ // Issue #352: When formatting, use the precision of the underlying value
+ precision := 64
+ if in.Kind() == reflect.Float32 {
+ precision = 32
+ }
+
+ s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
+ switch s {
+ case "+Inf":
+ s = ".inf"
+ case "-Inf":
+ s = "-.inf"
+ case "NaN":
+ s = ".nan"
+ }
+ e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) nilv() {
+ e.emitScalar("null", "", "", yaml_PLAIN_SCALAR_STYLE, nil, nil, nil, nil)
+}
+
+func (e *encoder) emitScalar(value, anchor, tag string, style yaml_scalar_style_t, head, line, foot, tail []byte) {
+ // TODO Kill this function. Replace all initialize calls by their underlining Go literals.
+ implicit := tag == ""
+ if !implicit {
+ tag = longTag(tag)
+ }
+ e.must(yaml_scalar_event_initialize(&e.event, []byte(anchor), []byte(tag), []byte(value), implicit, implicit, style))
+ e.event.head_comment = head
+ e.event.line_comment = line
+ e.event.foot_comment = foot
+ e.event.tail_comment = tail
+ e.emit()
+}
+
+func (e *encoder) nodev(in reflect.Value) {
+ e.node(in.Interface().(*Node), "")
+}
+
+func (e *encoder) node(node *Node, tail string) {
+ // Zero nodes behave as nil.
+ if node.Kind == 0 && node.IsZero() {
+ e.nilv()
+ return
+ }
+
+ // If the tag was not explicitly requested, and dropping it won't change the
+ // implicit tag of the value, don't include it in the presentation.
+ var tag = node.Tag
+ var stag = shortTag(tag)
+ var forceQuoting bool
+ if tag != "" && node.Style&TaggedStyle == 0 {
+ if node.Kind == ScalarNode {
+ if stag == strTag && node.Style&(SingleQuotedStyle|DoubleQuotedStyle|LiteralStyle|FoldedStyle) != 0 {
+ tag = ""
+ } else {
+ rtag, _ := resolve("", node.Value)
+ if rtag == stag {
+ tag = ""
+ } else if stag == strTag {
+ tag = ""
+ forceQuoting = true
+ }
+ }
+ } else {
+ var rtag string
+ switch node.Kind {
+ case MappingNode:
+ rtag = mapTag
+ case SequenceNode:
+ rtag = seqTag
+ }
+ if rtag == stag {
+ tag = ""
+ }
+ }
+ }
+
+ switch node.Kind {
+ case DocumentNode:
+ yaml_document_start_event_initialize(&e.event, nil, nil, true)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ yaml_document_end_event_initialize(&e.event, true)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case SequenceNode:
+ style := yaml_BLOCK_SEQUENCE_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_SEQUENCE_STYLE
+ }
+ e.must(yaml_sequence_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+ for _, node := range node.Content {
+ e.node(node, "")
+ }
+ e.must(yaml_sequence_end_event_initialize(&e.event))
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case MappingNode:
+ style := yaml_BLOCK_MAPPING_STYLE
+ if node.Style&FlowStyle != 0 {
+ style = yaml_FLOW_MAPPING_STYLE
+ }
+ yaml_mapping_start_event_initialize(&e.event, []byte(node.Anchor), []byte(longTag(tag)), tag == "", style)
+ e.event.tail_comment = []byte(tail)
+ e.event.head_comment = []byte(node.HeadComment)
+ e.emit()
+
+ // The tail logic below moves the foot comment of prior keys to the following key,
+ // since the value for each key may be a nested structure and the foot needs to be
+ // processed only the entirety of the value is streamed. The last tail is processed
+ // with the mapping end event.
+ var tail string
+ for i := 0; i+1 < len(node.Content); i += 2 {
+ k := node.Content[i]
+ foot := k.FootComment
+ if foot != "" {
+ kopy := *k
+ kopy.FootComment = ""
+ k = &kopy
+ }
+ e.node(k, tail)
+ tail = foot
+
+ v := node.Content[i+1]
+ e.node(v, "")
+ }
+
+ yaml_mapping_end_event_initialize(&e.event)
+ e.event.tail_comment = []byte(tail)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case AliasNode:
+ yaml_alias_event_initialize(&e.event, []byte(node.Value))
+ e.event.head_comment = []byte(node.HeadComment)
+ e.event.line_comment = []byte(node.LineComment)
+ e.event.foot_comment = []byte(node.FootComment)
+ e.emit()
+
+ case ScalarNode:
+ value := node.Value
+ if !utf8.ValidString(value) {
+ if stag == binaryTag {
+ failf("explicitly tagged !!binary data must be base64-encoded")
+ }
+ if stag != "" {
+ failf("cannot marshal invalid UTF-8 data as %s", stag)
+ }
+ // It can't be encoded directly as YAML so use a binary tag
+ // and encode it as base64.
+ tag = binaryTag
+ value = encodeBase64(value)
+ }
+
+ style := yaml_PLAIN_SCALAR_STYLE
+ switch {
+ case node.Style&DoubleQuotedStyle != 0:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ case node.Style&SingleQuotedStyle != 0:
+ style = yaml_SINGLE_QUOTED_SCALAR_STYLE
+ case node.Style&LiteralStyle != 0:
+ style = yaml_LITERAL_SCALAR_STYLE
+ case node.Style&FoldedStyle != 0:
+ style = yaml_FOLDED_SCALAR_STYLE
+ case strings.Contains(value, "\n"):
+ style = yaml_LITERAL_SCALAR_STYLE
+ case forceQuoting:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
+ }
+
+ e.emitScalar(value, node.Anchor, tag, style, []byte(node.HeadComment), []byte(node.LineComment), []byte(node.FootComment), []byte(tail))
+ default:
+ failf("cannot encode node with unknown kind %d", node.Kind)
+ }
+}
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/encode_test.go b/kyaml/internal/forked/github.com/go-yaml/yaml/encode_test.go
new file mode 100644
index 000000000..b5bf34689
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/encode_test.go
@@ -0,0 +1,884 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml_test
+
+import (
+ "bytes"
+ "fmt"
+ "math"
+ "strconv"
+ "strings"
+ "time"
+
+ "net"
+ "os"
+
+ . "gopkg.in/check.v1"
+ "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
+)
+
+var marshalIntTest = 123
+
+var marshalTests = []struct {
+ value interface{}
+ data string
+ compact string
+}{
+ {
+ nil,
+ "null\n",
+ "null\n",
+ }, {
+ (*marshalerType)(nil),
+ "null\n",
+ "null\n",
+ }, {
+ &struct{}{},
+ "{}\n",
+ "{}\n",
+ }, {
+ map[string]string{"v": "hi"},
+ "v: hi\n",
+ "v: hi\n",
+ }, {
+ map[string]interface{}{"v": "hi"},
+ "v: hi\n",
+ "v: hi\n",
+ }, {
+ map[string]string{"v": "true"},
+ "v: \"true\"\n",
+ "v: \"true\"\n",
+ }, {
+ map[string]string{"v": "false"},
+ "v: \"false\"\n",
+ "v: \"false\"\n",
+ }, {
+ map[string]interface{}{"v": true},
+ "v: true\n",
+ "v: true\n",
+ }, {
+ map[string]interface{}{"v": false},
+ "v: false\n",
+ "v: false\n",
+ }, {
+ map[string]interface{}{"v": 10},
+ "v: 10\n",
+ "v: 10\n",
+ }, {
+ map[string]interface{}{"v": -10},
+ "v: -10\n",
+ "v: -10\n",
+ }, {
+ map[string]uint{"v": 42},
+ "v: 42\n",
+ "v: 42\n",
+ }, {
+ map[string]interface{}{"v": int64(4294967296)},
+ "v: 4294967296\n",
+ "v: 4294967296\n",
+ }, {
+ map[string]int64{"v": int64(4294967296)},
+ "v: 4294967296\n",
+ "v: 4294967296\n",
+ }, {
+ map[string]uint64{"v": 4294967296},
+ "v: 4294967296\n",
+ "v: 4294967296\n",
+ }, {
+ map[string]interface{}{"v": "10"},
+ "v: \"10\"\n",
+ "v: \"10\"\n",
+ }, {
+ map[string]interface{}{"v": 0.1},
+ "v: 0.1\n",
+ "v: 0.1\n",
+ }, {
+ map[string]interface{}{"v": float64(0.1)},
+ "v: 0.1\n",
+ "v: 0.1\n",
+ }, {
+ map[string]interface{}{"v": float32(0.99)},
+ "v: 0.99\n",
+ "v: 0.99\n",
+ }, {
+ map[string]interface{}{"v": -0.1},
+ "v: -0.1\n",
+ "v: -0.1\n",
+ }, {
+ map[string]interface{}{"v": math.Inf(+1)},
+ "v: .inf\n",
+ "v: .inf\n",
+ }, {
+ map[string]interface{}{"v": math.Inf(-1)},
+ "v: -.inf\n",
+ "v: -.inf\n",
+ }, {
+ map[string]interface{}{"v": math.NaN()},
+ "v: .nan\n",
+ "v: .nan\n",
+ }, {
+ map[string]interface{}{"v": nil},
+ "v: null\n",
+ "v: null\n",
+ }, {
+ map[string]interface{}{"v": ""},
+ "v: \"\"\n",
+ "v: \"\"\n",
+ }, {
+ map[string][]string{"v": {"A", "B"}},
+ "v:\n - A\n - B\n",
+ "v:\n - A\n - B\n",
+ }, {
+ map[string][]string{"v": {"A", "B\nC"}},
+ "v:\n - A\n - |-\n B\n C\n",
+ "v:\n - A\n - |-\n B\n C\n",
+ }, {
+ map[string][]interface{}{"v": {"A", 1, map[string][]int{"B": {2, 3}}}},
+ "v:\n - A\n - 1\n - B:\n - 2\n - 3\n",
+ "v:\n - A\n - 1\n - B:\n - 2\n - 3\n",
+ }, {
+ map[string]interface{}{"a": map[interface{}]interface{}{"b": "c"}},
+ "a:\n b: c\n",
+ "a:\n b: c\n",
+ }, {
+ map[string]interface{}{"a": "-"},
+ "a: '-'\n",
+ "a: '-'\n",
+ },
+
+ // Simple values.
+ {
+ &marshalIntTest,
+ "123\n",
+ "123\n",
+ },
+
+ // Structures
+ {
+ &struct{ Hello string }{"world"},
+ "hello: world\n",
+ "hello: world\n",
+ }, {
+ &struct {
+ A struct {
+ B string
+ }
+ }{struct{ B string }{"c"}},
+ "a:\n b: c\n",
+ "a:\n b: c\n",
+ }, {
+ &struct {
+ A *struct {
+ B string
+ }
+ }{&struct{ B string }{"c"}},
+ "a:\n b: c\n",
+ "a:\n b: c\n",
+ }, {
+ &struct {
+ A *struct {
+ B string
+ }
+ }{},
+ "a: null\n",
+ "a: null\n",
+ }, {
+ &struct{ A int }{1},
+ "a: 1\n",
+ "a: 1\n",
+ }, {
+ &struct{ A []int }{[]int{1, 2}},
+ "a:\n - 1\n - 2\n",
+ "a:\n - 1\n - 2\n",
+ }, {
+ &struct{ A [2]int }{[2]int{1, 2}},
+ "a:\n - 1\n - 2\n",
+ "a:\n - 1\n - 2\n",
+ }, {
+ &struct {
+ B int "a"
+ }{1},
+ "a: 1\n",
+ "a: 1\n",
+ }, {
+ &struct{ A bool }{true},
+ "a: true\n",
+ "a: true\n",
+ }, {
+ &struct{ A string }{"true"},
+ "a: \"true\"\n",
+ "a: \"true\"\n",
+ }, {
+ &struct{ A string }{"off"},
+ "a: \"off\"\n",
+ "a: \"off\"\n",
+ },
+
+ // Conditional flag
+ {
+ &struct {
+ A int "a,omitempty"
+ B int "b,omitempty"
+ }{1, 0},
+ "a: 1\n",
+ "a: 1\n",
+ }, {
+ &struct {
+ A int "a,omitempty"
+ B int "b,omitempty"
+ }{0, 0},
+ "{}\n",
+ "{}\n",
+ }, {
+ &struct {
+ A *struct{ X, y int } "a,omitempty,flow"
+ }{&struct{ X, y int }{1, 2}},
+ "a: {x: 1}\n",
+ "a: {x: 1}\n",
+ }, {
+ &struct {
+ A *struct{ X, y int } "a,omitempty,flow"
+ }{nil},
+ "{}\n",
+ "{}\n",
+ }, {
+ &struct {
+ A *struct{ X, y int } "a,omitempty,flow"
+ }{&struct{ X, y int }{}},
+ "a: {x: 0}\n",
+ "a: {x: 0}\n",
+ }, {
+ &struct {
+ A struct{ X, y int } "a,omitempty,flow"
+ }{struct{ X, y int }{1, 2}},
+ "a: {x: 1}\n",
+ "a: {x: 1}\n",
+ }, {
+ &struct {
+ A struct{ X, y int } "a,omitempty,flow"
+ }{struct{ X, y int }{0, 1}},
+ "{}\n",
+ "{}\n",
+ }, {
+ &struct {
+ A float64 "a,omitempty"
+ B float64 "b,omitempty"
+ }{1, 0},
+ "a: 1\n",
+ "a: 1\n",
+ },
+ {
+ &struct {
+ T1 time.Time "t1,omitempty"
+ T2 time.Time "t2,omitempty"
+ T3 *time.Time "t3,omitempty"
+ T4 *time.Time "t4,omitempty"
+ }{
+ T2: time.Date(2018, 1, 9, 10, 40, 47, 0, time.UTC),
+ T4: newTime(time.Date(2098, 1, 9, 10, 40, 47, 0, time.UTC)),
+ },
+ "t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
+ "t2: 2018-01-09T10:40:47Z\nt4: 2098-01-09T10:40:47Z\n",
+ },
+ // Nil interface that implements Marshaler.
+ {
+ map[string]yaml.Marshaler{
+ "a": nil,
+ },
+ "a: null\n",
+ "a: null\n",
+ },
+
+ // Flow flag
+ {
+ &struct {
+ A []int "a,flow"
+ }{[]int{1, 2}},
+ "a: [1, 2]\n",
+ "a: [1, 2]\n",
+ }, {
+ &struct {
+ A map[string]string "a,flow"
+ }{map[string]string{"b": "c", "d": "e"}},
+ "a: {b: c, d: e}\n",
+ "a: {b: c, d: e}\n",
+ }, {
+ &struct {
+ A struct {
+ B, D string
+ } "a,flow"
+ }{struct{ B, D string }{"c", "e"}},
+ "a: {b: c, d: e}\n",
+ "a: {b: c, d: e}\n",
+ }, {
+ &struct {
+ A string "a,flow"
+ }{"b\nc"},
+ "a: \"b\\nc\"\n",
+ "a: \"b\\nc\"\n",
+ },
+
+ // Unexported field
+ {
+ &struct {
+ u int
+ A int
+ }{0, 1},
+ "a: 1\n",
+ "a: 1\n",
+ },
+
+ // Ignored field
+ {
+ &struct {
+ A int
+ B int "-"
+ }{1, 2},
+ "a: 1\n",
+ "a: 1\n",
+ },
+
+ // Struct inlining
+ {
+ &struct {
+ A int
+ C inlineB `yaml:",inline"`
+ }{1, inlineB{2, inlineC{3}}},
+ "a: 1\nb: 2\nc: 3\n",
+ "a: 1\nb: 2\nc: 3\n",
+ },
+ // Struct inlining as a pointer
+ {
+ &struct {
+ A int
+ C *inlineB `yaml:",inline"`
+ }{1, &inlineB{2, inlineC{3}}},
+ "a: 1\nb: 2\nc: 3\n",
+ "a: 1\nb: 2\nc: 3\n",
+ }, {
+ &struct {
+ A int
+ C *inlineB `yaml:",inline"`
+ }{1, nil},
+ "a: 1\n",
+ "a: 1\n",
+ }, {
+ &struct {
+ A int
+ D *inlineD `yaml:",inline"`
+ }{1, &inlineD{&inlineC{3}, 4}},
+ "a: 1\nc: 3\nd: 4\n",
+ "a: 1\nc: 3\nd: 4\n",
+ },
+
+ // Map inlining
+ {
+ &struct {
+ A int
+ C map[string]int `yaml:",inline"`
+ }{1, map[string]int{"b": 2, "c": 3}},
+ "a: 1\nb: 2\nc: 3\n",
+ "a: 1\nb: 2\nc: 3\n",
+ },
+
+ // Duration
+ {
+ map[string]time.Duration{"a": 3 * time.Second},
+ "a: 3s\n",
+ "a: 3s\n",
+ },
+
+ // Issue #24: bug in map merging logic.
+ {
+ map[string]string{"a": ""},
+ "a: \n",
+ "a: \n",
+ },
+
+ // Issue #34: marshal unsupported base 60 floats quoted for compatibility
+ // with old YAML 1.1 parsers.
+ {
+ map[string]string{"a": "1:1"},
+ "a: \"1:1\"\n",
+ "a: \"1:1\"\n",
+ },
+
+ // Binary data.
+ {
+ map[string]string{"a": "\x00"},
+ "a: \"\\0\"\n",
+ "a: \"\\0\"\n",
+ }, {
+ map[string]string{"a": "\x80\x81\x82"},
+ "a: !!binary gIGC\n",
+ "a: !!binary gIGC\n",
+ }, {
+ map[string]string{"a": strings.Repeat("\x90", 54)},
+ "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
+ "a: !!binary |\n " + strings.Repeat("kJCQ", 17) + "kJ\n CQ\n",
+ },
+
+ // Encode unicode as utf-8 rather than in escaped form.
+ {
+ map[string]string{"a": "你好"},
+ "a: 你好\n",
+ "a: 你好\n",
+ },
+
+ // Support encoding.TextMarshaler.
+ {
+ map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
+ "a: 1.2.3.4\n",
+ "a: 1.2.3.4\n",
+ },
+ // time.Time gets a timestamp tag.
+ {
+ map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC)},
+ "a: 2015-02-24T18:19:39Z\n",
+ "a: 2015-02-24T18:19:39Z\n",
+ },
+ {
+ map[string]*time.Time{"a": newTime(time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC))},
+ "a: 2015-02-24T18:19:39Z\n",
+ "a: 2015-02-24T18:19:39Z\n",
+ },
+ {
+ // This is confirmed to be properly decoded in Python (libyaml) without a timestamp tag.
+ map[string]time.Time{"a": time.Date(2015, 2, 24, 18, 19, 39, 123456789, time.FixedZone("FOO", -3*60*60))},
+ "a: 2015-02-24T18:19:39.123456789-03:00\n",
+ "a: 2015-02-24T18:19:39.123456789-03:00\n",
+ },
+ // Ensure timestamp-like strings are quoted.
+ {
+ map[string]string{"a": "2015-02-24T18:19:39Z"},
+ "a: \"2015-02-24T18:19:39Z\"\n",
+ "a: \"2015-02-24T18:19:39Z\"\n",
+ },
+
+ // Ensure strings containing ": " are quoted (reported as PR #43, but not reproducible).
+ {
+ map[string]string{"a": "b: c"},
+ "a: 'b: c'\n",
+ "a: 'b: c'\n",
+ },
+
+ // Containing hash mark ('#') in string should be quoted
+ {
+ map[string]string{"a": "Hello #comment"},
+ "a: 'Hello #comment'\n",
+ "a: 'Hello #comment'\n",
+ },
+ {
+ map[string]string{"a": "你好 #comment"},
+ "a: '你好 #comment'\n",
+ "a: '你好 #comment'\n",
+ },
+
+ // Ensure MarshalYAML also gets called on the result of MarshalYAML itself.
+ {
+ &marshalerType{marshalerType{true}},
+ "true\n",
+ "true\n",
+ }, {
+ &marshalerType{&marshalerType{true}},
+ "true\n",
+ "true\n",
+ },
+
+ // Check indentation of maps inside sequences inside maps.
+ {
+ map[string]interface{}{"a": map[string]interface{}{"b": []map[string]int{{"c": 1, "d": 2}}}},
+ "a:\n b:\n - c: 1\n d: 2\n",
+ "a:\n b:\n - c: 1\n d: 2\n",
+ },
+
+ // Strings with tabs were disallowed as literals (issue #471).
+ {
+ map[string]string{"a": "\tB\n\tC\n"},
+ "a: |\n \tB\n \tC\n",
+ "a: |\n \tB\n \tC\n",
+ },
+
+ // Ensure that strings do not wrap
+ {
+ map[string]string{"a": "abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 "},
+ "a: 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 '\n",
+ "a: 'abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ 1234567890 '\n",
+ },
+
+ // yaml.Node
+ {
+ &struct {
+ Value yaml.Node
+ }{
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "foo",
+ Style: yaml.SingleQuotedStyle,
+ },
+ },
+ "value: 'foo'\n",
+ "value: 'foo'\n",
+ }, {
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "foo",
+ Style: yaml.SingleQuotedStyle,
+ },
+ "'foo'\n",
+ "'foo'\n",
+ },
+
+ // Enforced tagging with shorthand notation (issue #616).
+ {
+ &struct {
+ Value yaml.Node
+ }{
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Style: yaml.TaggedStyle,
+ Value: "foo",
+ Tag: "!!str",
+ },
+ },
+ "value: !!str foo\n",
+ "value: !!str foo\n",
+ }, {
+ &struct {
+ Value yaml.Node
+ }{
+ yaml.Node{
+ Kind: yaml.MappingNode,
+ Style: yaml.TaggedStyle,
+ Tag: "!!map",
+ },
+ },
+ "value: !!map {}\n",
+ "value: !!map {}\n",
+ }, {
+ &struct {
+ Value yaml.Node
+ }{
+ yaml.Node{
+ Kind: yaml.SequenceNode,
+ Style: yaml.TaggedStyle,
+ Tag: "!!seq",
+ },
+ },
+ "value: !!seq []\n",
+ "value: !!seq []\n",
+ },
+}
+
+func (s *S) TestMarshal(c *C) {
+ defer os.Setenv("TZ", os.Getenv("TZ"))
+ os.Setenv("TZ", "UTC")
+ for i, item := range marshalTests {
+ c.Logf("test %d: %q", i, item.data)
+ data, err := yaml.Marshal(item.value)
+ c.Assert(err, IsNil)
+ c.Assert(string(data), Equals, item.data)
+ }
+}
+
+func (s *S) TestEncoderCompactIndents(c *C) {
+ for i, item := range marshalTests {
+ c.Logf("test %d. %q", i, item.data)
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ enc.CompactSeqIndent()
+ err := enc.Encode(item.value)
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ c.Assert(buf.String(), Equals, item.compact)
+ }
+}
+
+func (s *S) TestEncoderSingleDocument(c *C) {
+ for i, item := range marshalTests {
+ c.Logf("test %d. %q", i, item.data)
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ err := enc.Encode(item.value)
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ c.Assert(buf.String(), Equals, item.data)
+ }
+}
+
+func (s *S) TestEncoderMultipleDocuments(c *C) {
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ err := enc.Encode(map[string]string{"a": "b"})
+ c.Assert(err, Equals, nil)
+ err = enc.Encode(map[string]string{"c": "d"})
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ c.Assert(buf.String(), Equals, "a: b\n---\nc: d\n")
+}
+
+func (s *S) TestEncoderWriteError(c *C) {
+ enc := yaml.NewEncoder(errorWriter{})
+ err := enc.Encode(map[string]string{"a": "b"})
+ c.Assert(err, ErrorMatches, `yaml: write error: some write error`) // Data not flushed yet
+}
+
+type errorWriter struct{}
+
+func (errorWriter) Write([]byte) (int, error) {
+ return 0, fmt.Errorf("some write error")
+}
+
+var marshalErrorTests = []struct {
+ value interface{}
+ error string
+ panic string
+}{{
+ value: &struct {
+ B int
+ inlineB ",inline"
+ }{1, inlineB{2, inlineC{3}}},
+ panic: `duplicated key 'b' in struct struct \{ B int; .*`,
+}, {
+ value: &struct {
+ A int
+ B map[string]int ",inline"
+ }{1, map[string]int{"a": 2}},
+ panic: `cannot have key "a" in inlined map: conflicts with struct field`,
+}}
+
+func (s *S) TestMarshalErrors(c *C) {
+ for _, item := range marshalErrorTests {
+ if item.panic != "" {
+ c.Assert(func() { yaml.Marshal(item.value) }, PanicMatches, item.panic)
+ } else {
+ _, err := yaml.Marshal(item.value)
+ c.Assert(err, ErrorMatches, item.error)
+ }
+ }
+}
+
+func (s *S) TestMarshalTypeCache(c *C) {
+ var data []byte
+ var err error
+ func() {
+ type T struct{ A int }
+ data, err = yaml.Marshal(&T{})
+ c.Assert(err, IsNil)
+ }()
+ func() {
+ type T struct{ B int }
+ data, err = yaml.Marshal(&T{})
+ c.Assert(err, IsNil)
+ }()
+ c.Assert(string(data), Equals, "b: 0\n")
+}
+
+var marshalerTests = []struct {
+ data string
+ value interface{}
+}{
+ {"_:\n hi: there\n", map[interface{}]interface{}{"hi": "there"}},
+ {"_:\n - 1\n - A\n", []interface{}{1, "A"}},
+ {"_: 10\n", 10},
+ {"_: null\n", nil},
+ {"_: BAR!\n", "BAR!"},
+}
+
+type marshalerType struct {
+ value interface{}
+}
+
+func (o marshalerType) MarshalText() ([]byte, error) {
+ panic("MarshalText called on type with MarshalYAML")
+}
+
+func (o marshalerType) MarshalYAML() (interface{}, error) {
+ return o.value, nil
+}
+
+type marshalerValue struct {
+ Field marshalerType "_"
+}
+
+func (s *S) TestMarshaler(c *C) {
+ for _, item := range marshalerTests {
+ obj := &marshalerValue{}
+ obj.Field.value = item.value
+ data, err := yaml.Marshal(obj)
+ c.Assert(err, IsNil)
+ c.Assert(string(data), Equals, string(item.data))
+ }
+}
+
+func (s *S) TestMarshalerWholeDocument(c *C) {
+ obj := &marshalerType{}
+ obj.value = map[string]string{"hello": "world!"}
+ data, err := yaml.Marshal(obj)
+ c.Assert(err, IsNil)
+ c.Assert(string(data), Equals, "hello: world!\n")
+}
+
+type failingMarshaler struct{}
+
+func (ft *failingMarshaler) MarshalYAML() (interface{}, error) {
+ return nil, failingErr
+}
+
+func (s *S) TestMarshalerError(c *C) {
+ _, err := yaml.Marshal(&failingMarshaler{})
+ c.Assert(err, Equals, failingErr)
+}
+
+func (s *S) TestSetIndent(c *C) {
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ enc.SetIndent(8)
+ err := enc.Encode(map[string]interface{}{"a": map[string]interface{}{"b": map[string]string{"c": "d"}}})
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ c.Assert(buf.String(), Equals, "a:\n b:\n c: d\n")
+}
+
+func (s *S) TestCompactSeqIndentDefault(c *C) {
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ enc.CompactSeqIndent()
+ err := enc.Encode(map[string]interface{}{"a": []string{"b", "c"}})
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ // The default indent is 4, so these sequence elements get 2 indents as before
+ c.Assert(buf.String(), Equals, `a:
+ - b
+ - c
+`)
+}
+
+func (s *S) TestCompactSequenceWithSetIndent(c *C) {
+ var buf bytes.Buffer
+ enc := yaml.NewEncoder(&buf)
+ enc.CompactSeqIndent()
+ enc.SetIndent(2)
+ err := enc.Encode(map[string]interface{}{"a": []string{"b", "c"}})
+ c.Assert(err, Equals, nil)
+ err = enc.Close()
+ c.Assert(err, Equals, nil)
+ // The sequence indent is 2, so these sequence elements don't get indented at all
+ c.Assert(buf.String(), Equals, `a:
+- b
+- c
+`)
+}
+
+func (s *S) TestNewLinePreserved(c *C) {
+ obj := &marshalerValue{}
+ obj.Field.value = "a:\n b:\n c: d\n"
+ data, err := yaml.Marshal(obj)
+ c.Assert(err, IsNil)
+ c.Assert(string(data), Equals, "_: |\n a:\n b:\n c: d\n")
+
+ obj.Field.value = "\na:\n b:\n c: d\n"
+ data, err = yaml.Marshal(obj)
+ c.Assert(err, IsNil)
+ // the newline at the start of the file should be preserved
+ c.Assert(string(data), Equals, "_: |4\n\n a:\n b:\n c: d\n")
+}
+
+func (s *S) TestSortedOutput(c *C) {
+ order := []interface{}{
+ false,
+ true,
+ 1,
+ uint(1),
+ 1.0,
+ 1.1,
+ 1.2,
+ 2,
+ uint(2),
+ 2.0,
+ 2.1,
+ "",
+ ".1",
+ ".2",
+ ".a",
+ "1",
+ "2",
+ "a!10",
+ "a/0001",
+ "a/002",
+ "a/3",
+ "a/10",
+ "a/11",
+ "a/0012",
+ "a/100",
+ "a~10",
+ "ab/1",
+ "b/1",
+ "b/01",
+ "b/2",
+ "b/02",
+ "b/3",
+ "b/03",
+ "b1",
+ "b01",
+ "b3",
+ "c2.10",
+ "c10.2",
+ "d1",
+ "d7",
+ "d7abc",
+ "d12",
+ "d12a",
+ "e2b",
+ "e4b",
+ "e21a",
+ }
+ m := make(map[interface{}]int)
+ for _, k := range order {
+ m[k] = 1
+ }
+ data, err := yaml.Marshal(m)
+ c.Assert(err, IsNil)
+ out := "\n" + string(data)
+ last := 0
+ for i, k := range order {
+ repr := fmt.Sprint(k)
+ if s, ok := k.(string); ok {
+ if _, err = strconv.ParseFloat(repr, 32); s == "" || err == nil {
+ repr = `"` + repr + `"`
+ }
+ }
+ index := strings.Index(out, "\n"+repr+":")
+ if index == -1 {
+ c.Fatalf("%#v is not in the output: %#v", k, out)
+ }
+ if index < last {
+ c.Fatalf("%#v was generated before %#v: %q", k, order[i-1], out)
+ }
+ last = index
+ }
+}
+
+func newTime(t time.Time) *time.Time {
+ return &t
+}
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/example_embedded_test.go b/kyaml/internal/forked/github.com/go-yaml/yaml/example_embedded_test.go
new file mode 100644
index 000000000..82b2c073e
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/example_embedded_test.go
@@ -0,0 +1,56 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml_test
+
+import (
+ "fmt"
+ "log"
+
+ "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
+)
+
+// An example showing how to unmarshal embedded
+// structs from YAML.
+
+type StructA struct {
+ A string `yaml:"a"`
+}
+
+type StructB struct {
+ // Embedded structs are not treated as embedded in YAML by default. To do that,
+ // add the ",inline" annotation below
+ StructA `yaml:",inline"`
+ B string `yaml:"b"`
+}
+
+var data = `
+a: a string from struct A
+b: a string from struct B
+`
+
+func ExampleUnmarshal_embedded() {
+ var b StructB
+
+ err := yaml.Unmarshal([]byte(data), &b)
+ if err != nil {
+ log.Fatalf("cannot unmarshal data: %v", err)
+ }
+ fmt.Println(b.A)
+ fmt.Println(b.B)
+ // Output:
+ // a string from struct A
+ // a string from struct B
+}
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/limit_test.go b/kyaml/internal/forked/github.com/go-yaml/yaml/limit_test.go
new file mode 100644
index 000000000..9f6441bf9
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/limit_test.go
@@ -0,0 +1,128 @@
+package yaml_test
+
+import (
+ "strings"
+ "testing"
+
+ . "gopkg.in/check.v1"
+ "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
+)
+
+var limitTests = []struct {
+ name string
+ data []byte
+ error string
+}{
+ {
+ name: "1000kb of maps with 100 aliases",
+ data: []byte(`{a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-100) + `], b: &b [*a` + strings.Repeat(`,*a`, 99) + `]}`),
+ error: "yaml: document contains excessive aliasing",
+ }, {
+ name: "1000kb of deeply nested slices",
+ data: []byte(strings.Repeat(`[`, 1000*1024)),
+ error: "yaml: exceeded max depth of 10000",
+ }, {
+ name: "1000kb of deeply nested maps",
+ data: []byte("x: " + strings.Repeat(`{`, 1000*1024)),
+ error: "yaml: exceeded max depth of 10000",
+ }, {
+ name: "1000kb of deeply nested indents",
+ data: []byte(strings.Repeat(`- `, 1000*1024)),
+ error: "yaml: exceeded max depth of 10000",
+ }, {
+ name: "1000kb of 1000-indent lines",
+ data: []byte(strings.Repeat(strings.Repeat(`- `, 1000)+"\n", 1024/2)),
+ },
+ {name: "1kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1*1024/4-1) + `]`)},
+ {name: "10kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 10*1024/4-1) + `]`)},
+ {name: "100kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 100*1024/4-1) + `]`)},
+ {name: "1000kb of maps", data: []byte(`a: &a [{a}` + strings.Repeat(`,{a}`, 1000*1024/4-1) + `]`)},
+ {name: "1000kb slice nested at max-depth", data: []byte(strings.Repeat(`[`, 10000) + `1` + strings.Repeat(`,1`, 1000*1024/2-20000-1) + strings.Repeat(`]`, 10000))},
+ {name: "1000kb slice nested in maps at max-depth", data: []byte("{a,b:\n" + strings.Repeat(" {a,b:", 10000-2) + ` [1` + strings.Repeat(",1", 1000*1024/2-6*10000-1) + `]` + strings.Repeat(`}`, 10000-1))},
+ {name: "1000kb of 10000-nested lines", data: []byte(strings.Repeat(`- `+strings.Repeat(`[`, 10000)+strings.Repeat(`]`, 10000)+"\n", 1000*1024/20000))},
+}
+
+func (s *S) TestLimits(c *C) {
+ if testing.Short() {
+ return
+ }
+ for _, tc := range limitTests {
+ var v interface{}
+ err := yaml.Unmarshal(tc.data, &v)
+ if len(tc.error) > 0 {
+ c.Assert(err, ErrorMatches, tc.error, Commentf("testcase: %s", tc.name))
+ } else {
+ c.Assert(err, IsNil, Commentf("testcase: %s", tc.name))
+ }
+ }
+}
+
+func Benchmark1000KB100Aliases(b *testing.B) {
+ benchmark(b, "1000kb of maps with 100 aliases")
+}
+func Benchmark1000KBDeeplyNestedSlices(b *testing.B) {
+ benchmark(b, "1000kb of deeply nested slices")
+}
+func Benchmark1000KBDeeplyNestedMaps(b *testing.B) {
+ benchmark(b, "1000kb of deeply nested maps")
+}
+func Benchmark1000KBDeeplyNestedIndents(b *testing.B) {
+ benchmark(b, "1000kb of deeply nested indents")
+}
+func Benchmark1000KB1000IndentLines(b *testing.B) {
+ benchmark(b, "1000kb of 1000-indent lines")
+}
+func Benchmark1KBMaps(b *testing.B) {
+ benchmark(b, "1kb of maps")
+}
+func Benchmark10KBMaps(b *testing.B) {
+ benchmark(b, "10kb of maps")
+}
+func Benchmark100KBMaps(b *testing.B) {
+ benchmark(b, "100kb of maps")
+}
+func Benchmark1000KBMaps(b *testing.B) {
+ benchmark(b, "1000kb of maps")
+}
+
+func BenchmarkDeepSlice(b *testing.B) {
+ benchmark(b, "1000kb slice nested at max-depth")
+}
+
+func BenchmarkDeepFlow(b *testing.B) {
+ benchmark(b, "1000kb slice nested in maps at max-depth")
+}
+
+func Benchmark1000KBMaxDepthNested(b *testing.B) {
+ benchmark(b, "1000kb of 10000-nested lines")
+}
+
+func benchmark(b *testing.B, name string) {
+ for _, t := range limitTests {
+ if t.name != name {
+ continue
+ }
+
+ b.ResetTimer()
+
+ for i := 0; i < b.N; i++ {
+ var v interface{}
+ err := yaml.Unmarshal(t.data, &v)
+ if len(t.error) > 0 {
+ if err == nil {
+ b.Errorf("expected error, got none")
+ } else if err.Error() != t.error {
+ b.Errorf("expected error '%s', got '%s'", t.error, err.Error())
+ }
+ } else {
+ if err != nil {
+ b.Errorf("unexpected error: %v", err)
+ }
+ }
+ }
+
+ return
+ }
+
+ b.Errorf("testcase %q not found", name)
+}
diff --git a/kyaml/internal/forked/github.com/go-yaml/yaml/node_test.go b/kyaml/internal/forked/github.com/go-yaml/yaml/node_test.go
new file mode 100644
index 000000000..bfed08c96
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/node_test.go
@@ -0,0 +1,2886 @@
+//
+// Copyright (c) 2011-2019 Canonical Ltd
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package yaml_test
+
+import (
+ "bytes"
+ "fmt"
+ "os"
+
+ . "gopkg.in/check.v1"
+ "sigs.k8s.io/kustomize/kyaml/internal/forked/github.com/go-yaml/yaml"
+ "io"
+ "strings"
+)
+
+var nodeTests = []struct {
+ yaml string
+ node yaml.Node
+}{
+ {
+ "null\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "null",
+ Tag: "!!null",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "[encode]null\n",
+ yaml.Node{},
+ }, {
+ "foo\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "foo",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "\"foo\"\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: yaml.DoubleQuotedStyle,
+ Value: "foo",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "'foo'\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: yaml.SingleQuotedStyle,
+ Value: "foo",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "!!str 123\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: yaml.TaggedStyle,
+ Value: "123",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ // Although the node isn't TaggedStyle, dropping the tag would change the value.
+ "[encode]!!binary gIGC\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "gIGC",
+ Tag: "!!binary",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ // Item doesn't have a tag, but needs to be binary encoded due to its content.
+ "[encode]!!binary gIGC\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "\x80\x81\x82",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ // Same, but with strings we can just quote them.
+ "[encode]\"123\"\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "123",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "!tag:something 123\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: yaml.TaggedStyle,
+ Value: "123",
+ Tag: "!tag:something",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "[encode]!tag:something 123\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "123",
+ Tag: "!tag:something",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "!tag:something {}\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Style: yaml.TaggedStyle | yaml.FlowStyle,
+ Tag: "!tag:something",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "[encode]!tag:something {}\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Style: yaml.FlowStyle,
+ Tag: "!tag:something",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "!tag:something []\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Style: yaml.TaggedStyle | yaml.FlowStyle,
+ Tag: "!tag:something",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "[encode]!tag:something []\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Style: yaml.FlowStyle,
+ Tag: "!tag:something",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "''\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: yaml.SingleQuotedStyle,
+ Value: "",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "|\n foo\n bar\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: yaml.LiteralStyle,
+ Value: "foo\nbar\n",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "true\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "true",
+ Tag: "!!bool",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "-10\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "-10",
+ Tag: "!!int",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "4294967296\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "4294967296",
+ Tag: "!!int",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "0.1000\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "0.1000",
+ Tag: "!!float",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "-.inf\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "-.inf",
+ Tag: "!!float",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ ".nan\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: ".nan",
+ Tag: "!!float",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "{}\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Style: yaml.FlowStyle,
+ Value: "",
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ }},
+ },
+ }, {
+ "a: b c\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Value: "",
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "b c",
+ Tag: "!!str",
+ Line: 1,
+ Column: 4,
+ }},
+ }},
+ },
+ }, {
+ "a:\n b: c\n d: e\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ Line: 2,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "c",
+ Tag: "!!str",
+ Line: 2,
+ Column: 6,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "d",
+ Tag: "!!str",
+ Line: 3,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "e",
+ Tag: "!!str",
+ Line: 3,
+ Column: 6,
+ }},
+ }},
+ }},
+ },
+ }, {
+ "a:\n - b: c\n d: e\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 5,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ Line: 2,
+ Column: 5,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "c",
+ Tag: "!!str",
+ Line: 2,
+ Column: 8,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "d",
+ Tag: "!!str",
+ Line: 3,
+ Column: 5,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "e",
+ Tag: "!!str",
+ Line: 3,
+ Column: 8,
+ }},
+ }},
+ }},
+ }},
+ },
+ }, {
+ "a: # AI\n - b\nc:\n - d\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "a",
+ LineComment: "# AI",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "b",
+ Line: 2,
+ Column: 5,
+ }},
+ Line: 2,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "c",
+ Line: 3,
+ Column: 1,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "d",
+ Line: 4,
+ Column: 5,
+ }},
+ Line: 4,
+ Column: 3,
+ }},
+ }},
+ },
+ }, {
+ "[decode]a:\n # HM\n - # HB1\n # HB2\n b: # IB\n c # IC\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: 0x0,
+ Tag: "!!str",
+ Value: "a",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 3,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ HeadComment: "# HM",
+ Line: 5,
+ Column: 5,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "b",
+ HeadComment: "# HB1\n# HB2",
+ LineComment: "# IB",
+ Line: 5,
+ Column: 5,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "c",
+ LineComment: "# IC",
+ Line: 6,
+ Column: 7,
+ }},
+ }},
+ }},
+ }},
+ },
+ }, {
+ // When encoding the value above, it loses b's inline comment.
+ "[encode]a:\n # HM\n - # HB1\n # HB2\n b: c # IC\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Style: 0x0,
+ Tag: "!!str",
+ Value: "a",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 3,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ HeadComment: "# HM",
+ Line: 5,
+ Column: 5,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "b",
+ HeadComment: "# HB1\n# HB2",
+ LineComment: "# IB",
+ Line: 5,
+ Column: 5,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "c",
+ LineComment: "# IC",
+ Line: 6,
+ Column: 7,
+ }},
+ }},
+ }},
+ }},
+ },
+ }, {
+ // Multiple cases of comment inlining next to mapping keys.
+ "a: | # IA\n str\nb: >- # IB\n str\nc: # IC\n - str\nd: # ID\n str:\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "a",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Style: yaml.LiteralStyle,
+ Tag: "!!str",
+ Value: "str\n",
+ LineComment: "# IA",
+ Line: 1,
+ Column: 4,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "b",
+ Line: 3,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Style: yaml.FoldedStyle,
+ Tag: "!!str",
+ Value: "str",
+ LineComment: "# IB",
+ Line: 3,
+ Column: 4,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "c",
+ LineComment: "# IC",
+ Line: 5,
+ Column: 1,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 6,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "str",
+ Line: 6,
+ Column: 5,
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "d",
+ LineComment: "# ID",
+ Line: 7,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 8,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "str",
+ Line: 8,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!null",
+ Line: 8,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ // Indentless sequence.
+ "[decode]a:\n# HM\n- # HB1\n # HB2\n b: # IB\n c # IC\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "a",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 3,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ HeadComment: "# HM",
+ Line: 5,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "b",
+ HeadComment: "# HB1\n# HB2",
+ LineComment: "# IB",
+ Line: 5,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "c",
+ LineComment: "# IC",
+ Line: 6,
+ Column: 5,
+ }},
+ }},
+ }},
+ }},
+ },
+ }, {
+ "- a\n- b\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Value: "",
+ Tag: "!!seq",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ Line: 2,
+ Column: 3,
+ }},
+ }},
+ },
+ }, {
+ "- a\n- - b\n - c\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 3,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ Line: 2,
+ Column: 5,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "c",
+ Tag: "!!str",
+ Line: 3,
+ Column: 5,
+ }},
+ }},
+ }},
+ },
+ }, {
+ "[a, b]\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Style: yaml.FlowStyle,
+ Value: "",
+ Tag: "!!seq",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 2,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ Line: 1,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ "- a\n- [b, c]\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 3,
+ }, {
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Style: yaml.FlowStyle,
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ Line: 2,
+ Column: 4,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "c",
+ Tag: "!!str",
+ Line: 2,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ "a: &x 1\nb: &y 2\nc: *x\nd: *y\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Line: 1,
+ Column: 1,
+ Tag: "!!map",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ Line: 1,
+ Column: 1,
+ },
+ saveNode("x", &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "1",
+ Tag: "!!int",
+ Anchor: "x",
+ Line: 1,
+ Column: 4,
+ }),
+ {
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ Line: 2,
+ Column: 1,
+ },
+ saveNode("y", &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "2",
+ Tag: "!!int",
+ Anchor: "y",
+ Line: 2,
+ Column: 4,
+ }),
+ {
+ Kind: yaml.ScalarNode,
+ Value: "c",
+ Tag: "!!str",
+ Line: 3,
+ Column: 1,
+ }, {
+ Kind: yaml.AliasNode,
+ Value: "x",
+ Alias: dropNode("x"),
+ Line: 3,
+ Column: 4,
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "d",
+ Tag: "!!str",
+ Line: 4,
+ Column: 1,
+ }, {
+ Kind: yaml.AliasNode,
+ Value: "y",
+ Tag: "",
+ Alias: dropNode("y"),
+ Line: 4,
+ Column: 4,
+ }},
+ }},
+ },
+ }, {
+
+ "# One\n# Two\ntrue # Three\n# Four\n# Five\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 3,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "true",
+ Tag: "!!bool",
+ Line: 3,
+ Column: 1,
+ HeadComment: "# One\n# Two",
+ LineComment: "# Three",
+ FootComment: "# Four\n# Five",
+ }},
+ },
+ }, {
+
+ "# š\ntrue # š\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "true",
+ Tag: "!!bool",
+ Line: 2,
+ Column: 1,
+ HeadComment: "# š",
+ LineComment: "# š",
+ }},
+ },
+ }, {
+
+ "[decode]\n# One\n\n# Two\n\n# Three\ntrue # Four\n# Five\n\n# Six\n\n# Seven\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 7,
+ Column: 1,
+ HeadComment: "# One\n\n# Two",
+ FootComment: "# Six\n\n# Seven",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "true",
+ Tag: "!!bool",
+ Line: 7,
+ Column: 1,
+ HeadComment: "# Three",
+ LineComment: "# Four",
+ FootComment: "# Five",
+ }},
+ },
+ }, {
+ // Write out the pound character if missing from comments.
+ "[encode]# One\n# Two\ntrue # Three\n# Four\n# Five\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 3,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "true",
+ Tag: "!!bool",
+ Line: 3,
+ Column: 1,
+ HeadComment: "One\nTwo\n",
+ LineComment: "Three\n",
+ FootComment: "Four\nFive\n",
+ }},
+ },
+ }, {
+ "[encode]# One\n# Two\ntrue # Three\n# Four\n# Five\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 3,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "true",
+ Tag: "!!bool",
+ Line: 3,
+ Column: 1,
+ HeadComment: " One\n Two",
+ LineComment: " Three",
+ FootComment: " Four\n Five",
+ }},
+ },
+ }, {
+ "# DH1\n\n# DH2\n\n# H1\n# H2\ntrue # I\n# F1\n# F2\n\n# DF1\n\n# DF2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 7,
+ Column: 1,
+ HeadComment: "# DH1\n\n# DH2",
+ FootComment: "# DF1\n\n# DF2",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "true",
+ Tag: "!!bool",
+ Line: 7,
+ Column: 1,
+ HeadComment: "# H1\n# H2",
+ LineComment: "# I",
+ FootComment: "# F1\n# F2",
+ }},
+ },
+ }, {
+ "# DH1\n\n# DH2\n\n# HA1\n# HA2\nka: va # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\nkb: vb # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 7,
+ Column: 1,
+ HeadComment: "# DH1\n\n# DH2",
+ FootComment: "# DF1\n\n# DF2",
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 7,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Line: 7,
+ Column: 1,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1\n# HA2",
+ FootComment: "# FA1\n# FA2",
+ }, {
+ Kind: yaml.ScalarNode,
+ Line: 7,
+ Column: 5,
+ Tag: "!!str",
+ Value: "va",
+ LineComment: "# IA",
+ }, {
+ Kind: yaml.ScalarNode,
+ Line: 13,
+ Column: 1,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1\n# HB2",
+ FootComment: "# FB1\n# FB2",
+ }, {
+ Kind: yaml.ScalarNode,
+ Line: 13,
+ Column: 5,
+ Tag: "!!str",
+ Value: "vb",
+ LineComment: "# IB",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# DH2\n\n# HA1\n# HA2\n- la # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\n- lb # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 7,
+ Column: 1,
+ HeadComment: "# DH1\n\n# DH2",
+ FootComment: "# DF1\n\n# DF2",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 7,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 7,
+ Column: 3,
+ Value: "la",
+ HeadComment: "# HA1\n# HA2",
+ LineComment: "# IA",
+ FootComment: "# FA1\n# FA2",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 13,
+ Column: 3,
+ Value: "lb",
+ HeadComment: "# HB1\n# HB2",
+ LineComment: "# IB",
+ FootComment: "# FB1\n# FB2",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n- la # IA\n# HB1\n- lb\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 3,
+ Column: 1,
+ HeadComment: "# DH1",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 3,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 3,
+ Column: 3,
+ Value: "la",
+ LineComment: "# IA",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 5,
+ Column: 3,
+ Value: "lb",
+ HeadComment: "# HB1",
+ }},
+ }},
+ },
+ }, {
+ "- la # IA\n- lb # IB\n- lc # IC\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 1,
+ Column: 3,
+ Value: "la",
+ LineComment: "# IA",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 2,
+ Column: 3,
+ Value: "lb",
+ LineComment: "# IB",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 3,
+ Column: 3,
+ Value: "lc",
+ LineComment: "# IC",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# HL1\n- - la\n # HB1\n - lb\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 4,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 4,
+ Column: 3,
+ HeadComment: "# HL1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 4,
+ Column: 5,
+ Value: "la",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 5,
+ Value: "lb",
+ HeadComment: "# HB1",
+ }},
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# HL1\n- # HA1\n - la\n # HB1\n - lb\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 4,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 5,
+ Column: 3,
+ HeadComment: "# HL1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 5,
+ Column: 5,
+ Value: "la",
+ HeadComment: "# HA1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 7,
+ Column: 5,
+ Value: "lb",
+ HeadComment: "# HB1",
+ }},
+ }},
+ }},
+ },
+ }, {
+ "[decode]# DH1\n\n# HL1\n- # HA1\n\n - la\n # HB1\n - lb\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 4,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 6,
+ Column: 3,
+ HeadComment: "# HL1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 5,
+ Value: "la",
+ HeadComment: "# HA1\n",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 8,
+ Column: 5,
+ Value: "lb",
+ HeadComment: "# HB1",
+ }},
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# HA1\nka:\n # HB1\n kb:\n # HC1\n # HC2\n - lc # IC\n # FC1\n # FC2\n\n # HD1\n - ld # ID\n # FD1\n\n# DF1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ FootComment: "# DF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 4,
+ Column: 1,
+ Value: "ka",
+ HeadComment: "# HA1",
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 6,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 3,
+ Value: "kb",
+ HeadComment: "# HB1",
+ }, {
+ Kind: yaml.SequenceNode,
+ Line: 9,
+ Column: 5,
+ Tag: "!!seq",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 9,
+ Column: 7,
+ Value: "lc",
+ HeadComment: "# HC1\n# HC2",
+ LineComment: "# IC",
+ FootComment: "# FC1\n# FC2",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 14,
+ Column: 7,
+ Value: "ld",
+ HeadComment: "# HD1",
+
+ LineComment: "# ID",
+ FootComment: "# FD1",
+ }},
+ }},
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# HA1\nka:\n # HB1\n kb:\n # HC1\n # HC2\n - lc # IC\n # FC1\n # FC2\n\n # HD1\n - ld # ID\n # FD1\nke: ve\n\n# DF1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ FootComment: "# DF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 4,
+ Column: 1,
+ Value: "ka",
+ HeadComment: "# HA1",
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 6,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 3,
+ Value: "kb",
+ HeadComment: "# HB1",
+ }, {
+ Kind: yaml.SequenceNode,
+ Line: 9,
+ Column: 5,
+ Tag: "!!seq",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 9,
+ Column: 7,
+ Value: "lc",
+ HeadComment: "# HC1\n# HC2",
+ LineComment: "# IC",
+ FootComment: "# FC1\n# FC2",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 14,
+ Column: 7,
+ Value: "ld",
+ HeadComment: "# HD1",
+ LineComment: "# ID",
+ FootComment: "# FD1",
+ }},
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 16,
+ Column: 1,
+ Value: "ke",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 16,
+ Column: 5,
+ Value: "ve",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# DH2\n\n# HA1\n# HA2\nka:\n # HB1\n # HB2\n kb:\n" +
+ " # HC1\n # HC2\n kc:\n # HD1\n # HD2\n kd: vd\n # FD1\n # FD2\n" +
+ " # FC1\n # FC2\n # FB1\n # FB2\n# FA1\n# FA2\n\n# HE1\n# HE2\nke: ve\n# FE1\n# FE2\n\n# DF1\n\n# DF2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ HeadComment: "# DH1\n\n# DH2",
+ FootComment: "# DF1\n\n# DF2",
+ Line: 7,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 7,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1\n# HA2",
+ FootComment: "# FA1\n# FA2",
+ Line: 7,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 10,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1\n# HB2",
+ FootComment: "# FB1\n# FB2",
+ Line: 10,
+ Column: 3,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 13,
+ Column: 5,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ HeadComment: "# HC1\n# HC2",
+ FootComment: "# FC1\n# FC2",
+ Line: 13,
+ Column: 5,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 16,
+ Column: 7,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kd",
+ HeadComment: "# HD1\n# HD2",
+ FootComment: "# FD1\n# FD2",
+ Line: 16,
+ Column: 7,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vd",
+ Line: 16,
+ Column: 11,
+ }},
+ }},
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ke",
+ HeadComment: "# HE1\n# HE2",
+ FootComment: "# FE1\n# FE2",
+ Line: 28,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ve",
+ Line: 28,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ // Same as above but indenting ke in so it's also part of ka's value.
+ "# DH1\n\n# DH2\n\n# HA1\n# HA2\nka:\n # HB1\n # HB2\n kb:\n" +
+ " # HC1\n # HC2\n kc:\n # HD1\n # HD2\n kd: vd\n # FD1\n # FD2\n" +
+ " # FC1\n # FC2\n # FB1\n # FB2\n\n # HE1\n # HE2\n ke: ve\n # FE1\n # FE2\n# FA1\n# FA2\n\n# DF1\n\n# DF2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ HeadComment: "# DH1\n\n# DH2",
+ FootComment: "# DF1\n\n# DF2",
+ Line: 7,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 7,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1\n# HA2",
+ FootComment: "# FA1\n# FA2",
+ Line: 7,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 10,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1\n# HB2",
+ FootComment: "# FB1\n# FB2",
+ Line: 10,
+ Column: 3,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 13,
+ Column: 5,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ HeadComment: "# HC1\n# HC2",
+ FootComment: "# FC1\n# FC2",
+ Line: 13,
+ Column: 5,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 16,
+ Column: 7,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kd",
+ HeadComment: "# HD1\n# HD2",
+ FootComment: "# FD1\n# FD2",
+ Line: 16,
+ Column: 7,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vd",
+ Line: 16,
+ Column: 11,
+ }},
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ke",
+ HeadComment: "# HE1\n# HE2",
+ FootComment: "# FE1\n# FE2",
+ Line: 26,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ve",
+ Line: 26,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ // Decode only due to lack of newline at the end.
+ "[decode]# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# FA1",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ Line: 2,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ Line: 4,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 4,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ // Same as above, but with newline at the end.
+ "# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# FA1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ Line: 2,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ Line: 4,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 4,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ // Same as above, but without FB1.
+ "# HA1\nka:\n # HB1\n kb: vb\n# FA1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ Line: 2,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1",
+ Line: 4,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 4,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ // Same as above, but with two newlines at the end. Decode-only for that.
+ "[decode]# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# FA1\n\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ Line: 2,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ Line: 4,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 4,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ // Similar to above, but make HB1 look more like a footer of ka.
+ "[decode]# HA1\nka:\n# HB1\n\n kb: vb\n# FA1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ Line: 2,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 5,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1\n",
+ Line: 5,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 5,
+ Column: 7,
+ }},
+ }},
+ }},
+ },
+ }, {
+ "ka:\n kb: vb\n# FA1\n\nkc: vc\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ Line: 1,
+ Column: 1,
+ FootComment: "# FA1",
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ Line: 2,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 2,
+ Column: 7,
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ Line: 5,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vc",
+ Line: 5,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ "ka:\n kb: vb\n# HC1\nkc: vc\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ Line: 2,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 2,
+ Column: 7,
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ HeadComment: "# HC1",
+ Line: 4,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vc",
+ Line: 4,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ // Decode only due to empty line before HC1.
+ "[decode]ka:\n kb: vb\n\n# HC1\nkc: vc\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ Line: 2,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 2,
+ Column: 7,
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ HeadComment: "# HC1",
+ Line: 5,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vc",
+ Line: 5,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ // Decode-only due to empty lines around HC1.
+ "[decode]ka:\n kb: vb\n\n# HC1\n\nkc: vc\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ Line: 2,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 2,
+ Column: 7,
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ HeadComment: "# HC1\n",
+ Line: 6,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vc",
+ Line: 6,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ "ka: # IA\n kb: # IB\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ Line: 1,
+ Column: 1,
+ LineComment: "# IA",
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ Line: 2,
+ Column: 3,
+ LineComment: "# IB",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!null",
+ Line: 2,
+ Column: 6,
+ }},
+ }},
+ }},
+ },
+ }, {
+ "# HA1\nka:\n # HB1\n kb: vb\n # FB1\n# HC1\n# HC2\nkc: vc\n# FC1\n# FC2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1",
+ Line: 2,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ Line: 4,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 4,
+ Column: 7,
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ HeadComment: "# HC1\n# HC2",
+ FootComment: "# FC1\n# FC2",
+ Line: 8,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vc",
+ Line: 8,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ // Same as above, but decode only due to empty line between ka's value and kc's headers.
+ "[decode]# HA1\nka:\n # HB1\n kb: vb\n # FB1\n\n# HC1\n# HC2\nkc: vc\n# FC1\n# FC2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ HeadComment: "# HA1",
+ Line: 2,
+ Column: 1,
+ }, {
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 4,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ Line: 4,
+ Column: 3,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vb",
+ Line: 4,
+ Column: 7,
+ }},
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kc",
+ HeadComment: "# HC1\n# HC2",
+ FootComment: "# FC1\n# FC2",
+ Line: 9,
+ Column: 1,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "vc",
+ Line: 9,
+ Column: 5,
+ }},
+ }},
+ },
+ }, {
+ "# H1\n[la, lb] # I\n# F1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 2,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Style: yaml.FlowStyle,
+ Line: 2,
+ Column: 1,
+ HeadComment: "# H1",
+ LineComment: "# I",
+ FootComment: "# F1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 2,
+ Column: 2,
+ Value: "la",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 2,
+ Column: 6,
+ Value: "lb",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# SH1\n[\n # HA1\n la, # IA\n # FA1\n\n # HB1\n lb, # IB\n # FB1\n]\n# SF1\n\n# DF1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ FootComment: "# DF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Style: yaml.FlowStyle,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# SH1",
+ FootComment: "# SF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 3,
+ Value: "la",
+ HeadComment: "# HA1",
+ LineComment: "# IA",
+ FootComment: "# FA1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 10,
+ Column: 3,
+ Value: "lb",
+ HeadComment: "# HB1",
+ LineComment: "# IB",
+ FootComment: "# FB1",
+ }},
+ }},
+ },
+ }, {
+ // Same as above, but with extra newlines before FB1 and FB2
+ "[decode]# DH1\n\n# SH1\n[\n # HA1\n la, # IA\n # FA1\n\n # HB1\n lb, # IB\n\n\n # FB1\n\n# FB2\n]\n# SF1\n\n# DF1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ FootComment: "# DF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Style: yaml.FlowStyle,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# SH1",
+ FootComment: "# SF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 3,
+ Value: "la",
+ HeadComment: "# HA1",
+ LineComment: "# IA",
+ FootComment: "# FA1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 10,
+ Column: 3,
+ Value: "lb",
+ HeadComment: "# HB1",
+ LineComment: "# IB",
+ FootComment: "# FB1\n\n# FB2",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# SH1\n[\n # HA1\n la,\n # FA1\n\n # HB1\n lb,\n # FB1\n]\n# SF1\n\n# DF1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ FootComment: "# DF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Style: yaml.FlowStyle,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# SH1",
+ FootComment: "# SF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 3,
+ Value: "la",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 10,
+ Column: 3,
+ Value: "lb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ }},
+ }},
+ },
+ }, {
+ "ka:\n kb: [\n # HA1\n la,\n # FA1\n\n # HB1\n lb,\n # FB1\n ]\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Line: 1,
+ Column: 1,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "ka",
+ Line: 1,
+ Column: 1,
+ }, {
+ Kind: 0x4,
+ Tag: "!!map",
+ Line: 2,
+ Column: 3,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "kb",
+ Line: 2,
+ Column: 3,
+ }, {
+ Kind: yaml.SequenceNode,
+ Style: 0x20,
+ Tag: "!!seq",
+ Line: 2,
+ Column: 7,
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "la",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ Line: 4,
+ Column: 5,
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "lb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ Line: 8,
+ Column: 5,
+ }},
+ }},
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# MH1\n{\n # HA1\n ka: va, # IA\n # FA1\n\n # HB1\n kb: vb, # IB\n # FB1\n}\n# MF1\n\n# DF1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ FootComment: "# DF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Style: yaml.FlowStyle,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# MH1",
+ FootComment: "# MF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 3,
+ Value: "ka",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 7,
+ Value: "va",
+ LineComment: "# IA",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 10,
+ Column: 3,
+ Value: "kb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 10,
+ Column: 7,
+ Value: "vb",
+ LineComment: "# IB",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# MH1\n{\n # HA1\n ka: va,\n # FA1\n\n # HB1\n kb: vb,\n # FB1\n}\n# MF1\n\n# DF1\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# DH1",
+ FootComment: "# DF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Style: yaml.FlowStyle,
+ Line: 4,
+ Column: 1,
+ HeadComment: "# MH1",
+ FootComment: "# MF1",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 3,
+ Value: "ka",
+ HeadComment: "# HA1",
+ FootComment: "# FA1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 6,
+ Column: 7,
+ Value: "va",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 10,
+ Column: 3,
+ Value: "kb",
+ HeadComment: "# HB1",
+ FootComment: "# FB1",
+ }, {
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 10,
+ Column: 7,
+ Value: "vb",
+ }},
+ }},
+ },
+ }, {
+ "# DH1\n\n# DH2\n\n# HA1\n# HA2\n- &x la # IA\n# FA1\n# FA2\n\n# HB1\n# HB2\n- *x # IB\n# FB1\n# FB2\n\n# DF1\n\n# DF2\n",
+ yaml.Node{
+ Kind: yaml.DocumentNode,
+ Line: 7,
+ Column: 1,
+ HeadComment: "# DH1\n\n# DH2",
+ FootComment: "# DF1\n\n# DF2",
+ Content: []*yaml.Node{{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Line: 7,
+ Column: 1,
+ Content: []*yaml.Node{
+ saveNode("x", &yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Line: 7,
+ Column: 3,
+ Value: "la",
+ HeadComment: "# HA1\n# HA2",
+ LineComment: "# IA",
+ FootComment: "# FA1\n# FA2",
+ Anchor: "x",
+ }), {
+ Kind: yaml.AliasNode,
+ Line: 13,
+ Column: 3,
+ Value: "x",
+ Alias: dropNode("x"),
+ HeadComment: "# HB1\n# HB2",
+ LineComment: "# IB",
+ FootComment: "# FB1\n# FB2",
+ },
+ },
+ }},
+ },
+ },
+}
+
+func (s *S) TestNodeRoundtrip(c *C) {
+ defer os.Setenv("TZ", os.Getenv("TZ"))
+ os.Setenv("TZ", "UTC")
+ for i, item := range nodeTests {
+ c.Logf("test %d: %q", i, item.yaml)
+
+ if strings.Contains(item.yaml, "#") {
+ var buf bytes.Buffer
+ fprintComments(&buf, &item.node, " ")
+ c.Logf(" expected comments:\n%s", buf.Bytes())
+ }
+
+ decode := true
+ encode := true
+
+ testYaml := item.yaml
+ if s := strings.TrimPrefix(testYaml, "[decode]"); s != testYaml {
+ encode = false
+ testYaml = s
+ }
+ if s := strings.TrimPrefix(testYaml, "[encode]"); s != testYaml {
+ decode = false
+ testYaml = s
+ }
+
+ if decode {
+ var node yaml.Node
+ err := yaml.Unmarshal([]byte(testYaml), &node)
+ c.Assert(err, IsNil)
+ if strings.Contains(item.yaml, "#") {
+ var buf bytes.Buffer
+ fprintComments(&buf, &node, " ")
+ c.Logf(" obtained comments:\n%s", buf.Bytes())
+ }
+ c.Assert(&node, DeepEquals, &item.node)
+ }
+ if encode {
+ node := deepCopyNode(&item.node, nil)
+ buf := bytes.Buffer{}
+ enc := yaml.NewEncoder(&buf)
+ enc.SetIndent(2)
+ err := enc.Encode(node)
+ c.Assert(err, IsNil)
+ err = enc.Close()
+ c.Assert(err, IsNil)
+ c.Assert(buf.String(), Equals, testYaml)
+
+ // Ensure there were no mutations to the tree.
+ c.Assert(node, DeepEquals, &item.node)
+ }
+ }
+}
+
+func deepCopyNode(node *yaml.Node, cache map[*yaml.Node]*yaml.Node) *yaml.Node {
+ if n, ok := cache[node]; ok {
+ return n
+ }
+ if cache == nil {
+ cache = make(map[*yaml.Node]*yaml.Node)
+ }
+ copy := *node
+ cache[node] = ©
+ copy.Content = nil
+ for _, elem := range node.Content {
+ copy.Content = append(copy.Content, deepCopyNode(elem, cache))
+ }
+ if node.Alias != nil {
+ copy.Alias = deepCopyNode(node.Alias, cache)
+ }
+ return ©
+}
+
+var savedNodes = make(map[string]*yaml.Node)
+
+func saveNode(name string, node *yaml.Node) *yaml.Node {
+ savedNodes[name] = node
+ return node
+}
+
+func peekNode(name string) *yaml.Node {
+ return savedNodes[name]
+}
+
+func dropNode(name string) *yaml.Node {
+ node := savedNodes[name]
+ delete(savedNodes, name)
+ return node
+}
+
+var setStringTests = []struct {
+ str string
+ yaml string
+ node yaml.Node
+}{
+ {
+ "something simple",
+ "something simple\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "something simple",
+ Tag: "!!str",
+ },
+ }, {
+ `"quoted value"`,
+ "'\"quoted value\"'\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: `"quoted value"`,
+ Tag: "!!str",
+ },
+ }, {
+ "multi\nline",
+ "|-\n multi\n line\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "multi\nline",
+ Tag: "!!str",
+ Style: yaml.LiteralStyle,
+ },
+ }, {
+ "123",
+ "\"123\"\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "123",
+ Tag: "!!str",
+ },
+ }, {
+ "multi\nline\n",
+ "|\n multi\n line\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "multi\nline\n",
+ Tag: "!!str",
+ Style: yaml.LiteralStyle,
+ },
+ }, {
+ "\x80\x81\x82",
+ "!!binary gIGC\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "gIGC",
+ Tag: "!!binary",
+ },
+ },
+}
+
+func (s *S) TestSetString(c *C) {
+ defer os.Setenv("TZ", os.Getenv("TZ"))
+ os.Setenv("TZ", "UTC")
+ for i, item := range setStringTests {
+ c.Logf("test %d: %q", i, item.str)
+
+ var node yaml.Node
+
+ node.SetString(item.str)
+
+ c.Assert(node, DeepEquals, item.node)
+
+ buf := bytes.Buffer{}
+ enc := yaml.NewEncoder(&buf)
+ enc.SetIndent(2)
+ err := enc.Encode(&item.node)
+ c.Assert(err, IsNil)
+ err = enc.Close()
+ c.Assert(err, IsNil)
+ c.Assert(buf.String(), Equals, item.yaml)
+
+ var doc yaml.Node
+ err = yaml.Unmarshal([]byte(item.yaml), &doc)
+ c.Assert(err, IsNil)
+
+ var str string
+ err = node.Decode(&str)
+ c.Assert(err, IsNil)
+ c.Assert(str, Equals, item.str)
+ }
+}
+
+var nodeEncodeDecodeTests = []struct {
+ value interface{}
+ yaml string
+ node yaml.Node
+}{{
+ "something simple",
+ "something simple\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: "something simple",
+ Tag: "!!str",
+ },
+}, {
+ `"quoted value"`,
+ "'\"quoted value\"'\n",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Style: yaml.SingleQuotedStyle,
+ Value: `"quoted value"`,
+ Tag: "!!str",
+ },
+}, {
+ 123,
+ "123",
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Value: `123`,
+ Tag: "!!int",
+ },
+}, {
+ []interface{}{1, 2},
+ "[1, 2]",
+ yaml.Node{
+ Kind: yaml.SequenceNode,
+ Tag: "!!seq",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "1",
+ Tag: "!!int",
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "2",
+ Tag: "!!int",
+ }},
+ },
+}, {
+ map[string]interface{}{"a": "b"},
+ "a: b",
+ yaml.Node{
+ Kind: yaml.MappingNode,
+ Tag: "!!map",
+ Content: []*yaml.Node{{
+ Kind: yaml.ScalarNode,
+ Value: "a",
+ Tag: "!!str",
+ }, {
+ Kind: yaml.ScalarNode,
+ Value: "b",
+ Tag: "!!str",
+ }},
+ },
+}}
+
+func (s *S) TestNodeEncodeDecode(c *C) {
+ for i, item := range nodeEncodeDecodeTests {
+ c.Logf("Encode/Decode test value #%d: %#v", i, item.value)
+
+ var v interface{}
+ err := item.node.Decode(&v)
+ c.Assert(err, IsNil)
+ c.Assert(v, DeepEquals, item.value)
+
+ var n yaml.Node
+ err = n.Encode(item.value)
+ c.Assert(err, IsNil)
+ c.Assert(n, DeepEquals, item.node)
+ }
+}
+
+func (s *S) TestNodeZeroEncodeDecode(c *C) {
+ // Zero node value behaves as nil when encoding...
+ var n yaml.Node
+ data, err := yaml.Marshal(&n)
+ c.Assert(err, IsNil)
+ c.Assert(string(data), Equals, "null\n")
+
+ // ... and decoding.
+ var v *struct{} = &struct{}{}
+ c.Assert(n.Decode(&v), IsNil)
+ c.Assert(v, IsNil)
+
+ // ... and even when looking for its tag.
+ c.Assert(n.ShortTag(), Equals, "!!null")
+
+ // Kind zero is still unknown, though.
+ n.Line = 1
+ _, err = yaml.Marshal(&n)
+ c.Assert(err, ErrorMatches, "yaml: cannot encode node with unknown kind 0")
+ c.Assert(n.Decode(&v), ErrorMatches, "yaml: cannot decode node with unknown kind 0")
+}
+
+func (s *S) TestNodeOmitEmpty(c *C) {
+ var v struct {
+ A int
+ B yaml.Node ",omitempty"
+ }
+ v.A = 1
+ data, err := yaml.Marshal(&v)
+ c.Assert(err, IsNil)
+ c.Assert(string(data), Equals, "a: 1\n")
+
+ v.B.Line = 1
+ _, err = yaml.Marshal(&v)
+ c.Assert(err, ErrorMatches, "yaml: cannot encode node with unknown kind 0")
+}
+
+func fprintComments(out io.Writer, node *yaml.Node, indent string) {
+ switch node.Kind {
+ case yaml.ScalarNode:
+ fmt.Fprintf(out, "%s<%s> ", indent, node.Value)
+ fprintCommentSet(out, node)
+ fmt.Fprintf(out, "\n")
+ case yaml.DocumentNode:
+ fmt.Fprintf(out, "%s ", indent)
+ fprintCommentSet(out, node)
+ fmt.Fprintf(out, "\n")
+ for i := 0; i < len(node.Content); i++ {
+ fprintComments(out, node.Content[i], indent+" ")
+ }
+ case yaml.MappingNode:
+ fmt.Fprintf(out, "%s