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..5ade55007
--- /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"
+ "gopkg.in/yaml.v3"
+)
+
+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..0f47c9ca8
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/emitterc.go
@@ -0,0 +1,2020 @@
+//
+// 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) 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)
+ }
+ }
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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 {
+ if !yaml_emitter_increase_indent(emitter, false, false) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) {
+ 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) bool {
+ if len(emitter.line_comment) == 0 {
+ 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) {
+ 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) {
+ 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..4a8bf2e26
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/encode_test.go
@@ -0,0 +1,736 @@
+//
+// 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"
+ "gopkg.in/yaml.v3"
+)
+
+var marshalIntTest = 123
+
+var marshalTests = []struct {
+ value interface{}
+ data string
+}{
+ {
+ nil,
+ "null\n",
+ }, {
+ (*marshalerType)(nil),
+ "null\n",
+ }, {
+ &struct{}{},
+ "{}\n",
+ }, {
+ map[string]string{"v": "hi"},
+ "v: hi\n",
+ }, {
+ map[string]interface{}{"v": "hi"},
+ "v: hi\n",
+ }, {
+ map[string]string{"v": "true"},
+ "v: \"true\"\n",
+ }, {
+ map[string]string{"v": "false"},
+ "v: \"false\"\n",
+ }, {
+ map[string]interface{}{"v": true},
+ "v: true\n",
+ }, {
+ map[string]interface{}{"v": false},
+ "v: false\n",
+ }, {
+ map[string]interface{}{"v": 10},
+ "v: 10\n",
+ }, {
+ map[string]interface{}{"v": -10},
+ "v: -10\n",
+ }, {
+ map[string]uint{"v": 42},
+ "v: 42\n",
+ }, {
+ map[string]interface{}{"v": int64(4294967296)},
+ "v: 4294967296\n",
+ }, {
+ map[string]int64{"v": int64(4294967296)},
+ "v: 4294967296\n",
+ }, {
+ map[string]uint64{"v": 4294967296},
+ "v: 4294967296\n",
+ }, {
+ map[string]interface{}{"v": "10"},
+ "v: \"10\"\n",
+ }, {
+ map[string]interface{}{"v": 0.1},
+ "v: 0.1\n",
+ }, {
+ map[string]interface{}{"v": float64(0.1)},
+ "v: 0.1\n",
+ }, {
+ map[string]interface{}{"v": float32(0.99)},
+ "v: 0.99\n",
+ }, {
+ map[string]interface{}{"v": -0.1},
+ "v: -0.1\n",
+ }, {
+ map[string]interface{}{"v": math.Inf(+1)},
+ "v: .inf\n",
+ }, {
+ map[string]interface{}{"v": math.Inf(-1)},
+ "v: -.inf\n",
+ }, {
+ map[string]interface{}{"v": math.NaN()},
+ "v: .nan\n",
+ }, {
+ map[string]interface{}{"v": nil},
+ "v: null\n",
+ }, {
+ map[string]interface{}{"v": ""},
+ "v: \"\"\n",
+ }, {
+ map[string][]string{"v": []string{"A", "B"}},
+ "v:\n - A\n - B\n",
+ }, {
+ map[string][]string{"v": []string{"A", "B\nC"}},
+ "v:\n - A\n - |-\n B\n C\n",
+ }, {
+ map[string][]interface{}{"v": []interface{}{"A", 1, map[string][]int{"B": []int{2, 3}}}},
+ "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",
+ }, {
+ map[string]interface{}{"a": "-"},
+ "a: '-'\n",
+ },
+
+ // Simple values.
+ {
+ &marshalIntTest,
+ "123\n",
+ },
+
+ // Structures
+ {
+ &struct{ Hello string }{"world"},
+ "hello: world\n",
+ }, {
+ &struct {
+ A struct {
+ B string
+ }
+ }{struct{ B string }{"c"}},
+ "a:\n b: c\n",
+ }, {
+ &struct {
+ A *struct {
+ B string
+ }
+ }{&struct{ B string }{"c"}},
+ "a:\n b: c\n",
+ }, {
+ &struct {
+ A *struct {
+ B string
+ }
+ }{},
+ "a: null\n",
+ }, {
+ &struct{ A int }{1},
+ "a: 1\n",
+ }, {
+ &struct{ A []int }{[]int{1, 2}},
+ "a:\n - 1\n - 2\n",
+ }, {
+ &struct{ A [2]int }{[2]int{1, 2}},
+ "a:\n - 1\n - 2\n",
+ }, {
+ &struct {
+ B int "a"
+ }{1},
+ "a: 1\n",
+ }, {
+ &struct{ A bool }{true},
+ "a: true\n",
+ }, {
+ &struct{ A string }{"true"},
+ "a: \"true\"\n",
+ }, {
+ &struct{ A string }{"off"},
+ "a: \"off\"\n",
+ },
+
+ // Conditional flag
+ {
+ &struct {
+ A int "a,omitempty"
+ B int "b,omitempty"
+ }{1, 0},
+ "a: 1\n",
+ }, {
+ &struct {
+ A int "a,omitempty"
+ B int "b,omitempty"
+ }{0, 0},
+ "{}\n",
+ }, {
+ &struct {
+ A *struct{ X, y int } "a,omitempty,flow"
+ }{&struct{ X, y int }{1, 2}},
+ "a: {x: 1}\n",
+ }, {
+ &struct {
+ A *struct{ X, y int } "a,omitempty,flow"
+ }{nil},
+ "{}\n",
+ }, {
+ &struct {
+ A *struct{ X, y int } "a,omitempty,flow"
+ }{&struct{ X, y int }{}},
+ "a: {x: 0}\n",
+ }, {
+ &struct {
+ A struct{ X, y int } "a,omitempty,flow"
+ }{struct{ X, y int }{1, 2}},
+ "a: {x: 1}\n",
+ }, {
+ &struct {
+ A struct{ X, y int } "a,omitempty,flow"
+ }{struct{ X, y int }{0, 1}},
+ "{}\n",
+ }, {
+ &struct {
+ A float64 "a,omitempty"
+ B float64 "b,omitempty"
+ }{1, 0},
+ "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",
+ },
+ // Nil interface that implements Marshaler.
+ {
+ map[string]yaml.Marshaler{
+ "a": nil,
+ },
+ "a: null\n",
+ },
+
+ // Flow flag
+ {
+ &struct {
+ A []int "a,flow"
+ }{[]int{1, 2}},
+ "a: [1, 2]\n",
+ }, {
+ &struct {
+ A map[string]string "a,flow"
+ }{map[string]string{"b": "c", "d": "e"}},
+ "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",
+ }, {
+ &struct {
+ A string "a,flow"
+ }{"b\nc"},
+ "a: \"b\\nc\"\n",
+ },
+
+ // Unexported field
+ {
+ &struct {
+ u int
+ A int
+ }{0, 1},
+ "a: 1\n",
+ },
+
+ // Ignored field
+ {
+ &struct {
+ A int
+ B int "-"
+ }{1, 2},
+ "a: 1\n",
+ },
+
+ // Struct inlining
+ {
+ &struct {
+ A int
+ C inlineB `yaml:",inline"`
+ }{1, inlineB{2, inlineC{3}}},
+ "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",
+ }, {
+ &struct {
+ A int
+ C *inlineB `yaml:",inline"`
+ }{1, nil},
+ "a: 1\n",
+ }, {
+ &struct {
+ A int
+ D *inlineD `yaml:",inline"`
+ }{1, &inlineD{&inlineC{3}, 4}},
+ "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",
+ },
+
+ // Duration
+ {
+ map[string]time.Duration{"a": 3 * time.Second},
+ "a: 3s\n",
+ },
+
+ // Issue #24: bug in map merging logic.
+ {
+ map[string]string{"a": ""},
+ "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",
+ },
+
+ // Binary data.
+ {
+ map[string]string{"a": "\x00"},
+ "a: \"\\0\"\n",
+ }, {
+ map[string]string{"a": "\x80\x81\x82"},
+ "a: !!binary gIGC\n",
+ }, {
+ map[string]string{"a": strings.Repeat("\x90", 54)},
+ "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",
+ },
+
+ // Support encoding.TextMarshaler.
+ {
+ map[string]net.IP{"a": net.IPv4(1, 2, 3, 4)},
+ "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",
+ },
+ {
+ map[string]*time.Time{"a": newTime(time.Date(2015, 2, 24, 18, 19, 39, 0, time.UTC))},
+ "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",
+ },
+ // Ensure timestamp-like strings are quoted.
+ {
+ map[string]string{"a": "2015-02-24T18:19:39Z"},
+ "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",
+ },
+
+ // Containing hash mark ('#') in string should be quoted
+ {
+ map[string]string{"a": "Hello #comment"},
+ "a: 'Hello #comment'\n",
+ },
+ {
+ map[string]string{"a": "你好 #comment"},
+ "a: '你好 #comment'\n",
+ },
+
+ // Ensure MarshalYAML also gets called on the result of MarshalYAML itself.
+ {
+ &marshalerType{marshalerType{true}},
+ "true\n",
+ }, {
+ &marshalerType{&marshalerType{true}},
+ "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",
+ },
+
+ // Strings with tabs were disallowed as literals (issue #471).
+ {
+ map[string]string{"a": "\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",
+ },
+
+ // yaml.Node
+ {
+ &struct {
+ Value yaml.Node
+ }{
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "foo",
+ Style: yaml.SingleQuotedStyle,
+ },
+ },
+ "value: 'foo'\n",
+ }, {
+ yaml.Node{
+ Kind: yaml.ScalarNode,
+ Tag: "!!str",
+ Value: "foo",
+ Style: yaml.SingleQuotedStyle,
+ },
+ "'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",
+ }, {
+ &struct {
+ Value yaml.Node
+ }{
+ yaml.Node{
+ Kind: yaml.MappingNode,
+ Style: yaml.TaggedStyle,
+ Tag: "!!map",
+ },
+ },
+ "value: !!map {}\n",
+ }, {
+ &struct {
+ Value yaml.Node
+ }{
+ yaml.Node{
+ Kind: yaml.SequenceNode,
+ Style: yaml.TaggedStyle,
+ Tag: "!!seq",
+ },
+ },
+ "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) 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) 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..9d17398a5
--- /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"
+
+ "gopkg.in/yaml.v3"
+)
+
+// 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/go.mod b/kyaml/internal/forked/github.com/go-yaml/yaml/go.mod
new file mode 100644
index 000000000..f407ea321
--- /dev/null
+++ b/kyaml/internal/forked/github.com/go-yaml/yaml/go.mod
@@ -0,0 +1,5 @@
+module "gopkg.in/yaml.v3"
+
+require (
+ "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
+)
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..07a3cbd4b
--- /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"
+ "gopkg.in/yaml.v3"
+)
+
+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..b7d0c9a30
--- /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"
+ "gopkg.in/yaml.v3"
+ "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