summaryrefslogtreecommitdiffstats
path: root/vendor/gopkg.in/yaml.v2
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gopkg.in/yaml.v2')
-rw-r--r--vendor/gopkg.in/yaml.v2/.travis.yml3
-rw-r--r--vendor/gopkg.in/yaml.v2/NOTICE13
-rw-r--r--vendor/gopkg.in/yaml.v2/README.md2
-rw-r--r--vendor/gopkg.in/yaml.v2/apic.go55
-rw-r--r--vendor/gopkg.in/yaml.v2/decode.go238
-rw-r--r--vendor/gopkg.in/yaml.v2/decode_test.go1032
-rw-r--r--vendor/gopkg.in/yaml.v2/emitterc.go5
-rw-r--r--vendor/gopkg.in/yaml.v2/encode.go136
-rw-r--r--vendor/gopkg.in/yaml.v2/encode_test.go501
-rw-r--r--vendor/gopkg.in/yaml.v2/example_embedded_test.go41
-rw-r--r--vendor/gopkg.in/yaml.v2/go.mod5
-rw-r--r--vendor/gopkg.in/yaml.v2/readerc.go20
-rw-r--r--vendor/gopkg.in/yaml.v2/resolve.go80
-rw-r--r--vendor/gopkg.in/yaml.v2/scannerc.go29
-rw-r--r--vendor/gopkg.in/yaml.v2/sorter.go9
-rw-r--r--vendor/gopkg.in/yaml.v2/suite_test.go12
-rw-r--r--vendor/gopkg.in/yaml.v2/writerc.go65
-rw-r--r--vendor/gopkg.in/yaml.v2/yaml.go123
-rw-r--r--vendor/gopkg.in/yaml.v2/yamlh.go30
19 files changed, 553 insertions, 1846 deletions
diff --git a/vendor/gopkg.in/yaml.v2/.travis.yml b/vendor/gopkg.in/yaml.v2/.travis.yml
index 004172a2e..9f556934d 100644
--- a/vendor/gopkg.in/yaml.v2/.travis.yml
+++ b/vendor/gopkg.in/yaml.v2/.travis.yml
@@ -4,6 +4,9 @@ go:
- 1.4
- 1.5
- 1.6
+ - 1.7
+ - 1.8
+ - 1.9
- tip
go_import_path: gopkg.in/yaml.v2
diff --git a/vendor/gopkg.in/yaml.v2/NOTICE b/vendor/gopkg.in/yaml.v2/NOTICE
new file mode 100644
index 000000000..866d74a7a
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/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/vendor/gopkg.in/yaml.v2/README.md b/vendor/gopkg.in/yaml.v2/README.md
index 2ed3314c7..b50c6e877 100644
--- a/vendor/gopkg.in/yaml.v2/README.md
+++ b/vendor/gopkg.in/yaml.v2/README.md
@@ -48,8 +48,6 @@ The yaml package is licensed under the Apache License 2.0. Please see the LICENS
Example
-------
-Some more examples can be found in the "examples" folder.
-
```Go
package main
diff --git a/vendor/gopkg.in/yaml.v2/apic.go b/vendor/gopkg.in/yaml.v2/apic.go
index 95ec014e8..1f7e87e67 100644
--- a/vendor/gopkg.in/yaml.v2/apic.go
+++ b/vendor/gopkg.in/yaml.v2/apic.go
@@ -2,7 +2,6 @@ package yaml
import (
"io"
- "os"
)
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) {
@@ -48,9 +47,9 @@ func yaml_string_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err
return n, nil
}
-// File read handler.
-func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
- return parser.input_file.Read(buffer)
+// 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.
@@ -64,12 +63,12 @@ func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
}
// Set a file input.
-func yaml_parser_set_input_file(parser *yaml_parser_t, file *os.File) {
+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_file_read_handler
- parser.input_file = file
+ parser.read_handler = yaml_reader_read_handler
+ parser.input_reader = r
}
// Set the source encoding.
@@ -81,14 +80,13 @@ func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
}
// Create a new emitter object.
-func yaml_emitter_initialize(emitter *yaml_emitter_t) bool {
+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),
}
- return true
}
// Destroy an emitter object.
@@ -102,9 +100,10 @@ func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
return nil
}
-// File write handler.
-func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
- _, err := emitter.output_file.Write(buffer)
+// 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
}
@@ -118,12 +117,12 @@ func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]by
}
// Set a file output.
-func yaml_emitter_set_output_file(emitter *yaml_emitter_t, file io.Writer) {
+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_file_write_handler
- emitter.output_file = file
+ emitter.write_handler = yaml_writer_write_handler
+ emitter.output_writer = w
}
// Set the output encoding.
@@ -252,41 +251,41 @@ func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
//
// Create STREAM-START.
-func yaml_stream_start_event_initialize(event *yaml_event_t, encoding yaml_encoding_t) bool {
+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,
}
- return true
}
// Create STREAM-END.
-func yaml_stream_end_event_initialize(event *yaml_event_t) bool {
+func yaml_stream_end_event_initialize(event *yaml_event_t) {
*event = yaml_event_t{
typ: yaml_STREAM_END_EVENT,
}
- return true
}
// 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) bool {
+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,
}
- return true
}
// Create DOCUMENT-END.
-func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) bool {
+func yaml_document_end_event_initialize(event *yaml_event_t, implicit bool) {
*event = yaml_event_t{
typ: yaml_DOCUMENT_END_EVENT,
implicit: implicit,
}
- return true
}
///*
@@ -348,7 +347,7 @@ func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
}
// Create MAPPING-START.
-func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte, implicit bool, style yaml_mapping_style_t) bool {
+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,
@@ -356,15 +355,13 @@ func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte
implicit: implicit,
style: yaml_style_t(style),
}
- return true
}
// Create MAPPING-END.
-func yaml_mapping_end_event_initialize(event *yaml_event_t) bool {
+func yaml_mapping_end_event_initialize(event *yaml_event_t) {
*event = yaml_event_t{
typ: yaml_MAPPING_END_EVENT,
}
- return true
}
// Destroy an event object.
@@ -471,7 +468,7 @@ func yaml_event_delete(event *yaml_event_t) {
// } context
// tag_directive *yaml_tag_directive_t
//
-// context.error = YAML_NO_ERROR // Eliminate a compliler warning.
+// context.error = YAML_NO_ERROR // Eliminate a compiler warning.
//
// assert(document) // Non-NULL document object is expected.
//
diff --git a/vendor/gopkg.in/yaml.v2/decode.go b/vendor/gopkg.in/yaml.v2/decode.go
index e85eb2e3f..e4e56e28e 100644
--- a/vendor/gopkg.in/yaml.v2/decode.go
+++ b/vendor/gopkg.in/yaml.v2/decode.go
@@ -4,6 +4,7 @@ import (
"encoding"
"encoding/base64"
"fmt"
+ "io"
"math"
"reflect"
"strconv"
@@ -22,19 +23,22 @@ type node struct {
kind int
line, column int
tag string
- value string
- implicit bool
- children []*node
- anchors map[string]*node
+ // For an alias node, alias holds the resolved alias.
+ alias *node
+ value string
+ implicit bool
+ children []*node
+ anchors map[string]*node
}
// ----------------------------------------------------------------------------
// Parser, produces a node tree out of a libyaml event stream.
type parser struct {
- parser yaml_parser_t
- event yaml_event_t
- doc *node
+ parser yaml_parser_t
+ event yaml_event_t
+ doc *node
+ doneInit bool
}
func newParser(b []byte) *parser {
@@ -42,21 +46,30 @@ func newParser(b []byte) *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
+}
- p.skip()
- if p.event.typ != yaml_STREAM_START_EVENT {
- panic("expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
+func newParserFromReader(r io.Reader) *parser {
+ p := parser{}
+ if !yaml_parser_initialize(&p.parser) {
+ panic("failed to initialize YAML emitter")
}
- p.skip()
+ yaml_parser_set_input_reader(&p.parser, r)
return &p
}
+func (p *parser) init() {
+ if p.doneInit {
+ return
+ }
+ 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)
@@ -64,16 +77,35 @@ func (p *parser) destroy() {
yaml_parser_delete(&p.parser)
}
-func (p *parser) skip() {
- if p.event.typ != yaml_NO_EVENT {
- if p.event.typ == yaml_STREAM_END_EVENT {
- failf("attempted to go past the end of stream; corrupted value?")
+// 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()
}
- yaml_event_delete(&p.event)
+ }
+ 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() {
@@ -81,6 +113,10 @@ func (p *parser) fail() {
var line int
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++
+ }
} else if p.parser.context_mark.line != 0 {
line = p.parser.context_mark.line
}
@@ -103,7 +139,8 @@ func (p *parser) anchor(n *node, anchor []byte) {
}
func (p *parser) parse() *node {
- switch p.event.typ {
+ p.init()
+ switch p.peek() {
case yaml_SCALAR_EVENT:
return p.scalar()
case yaml_ALIAS_EVENT:
@@ -118,7 +155,7 @@ func (p *parser) parse() *node {
// Happens when attempting to decode an empty buffer.
return nil
default:
- panic("attempted to parse unknown event: " + strconv.Itoa(int(p.event.typ)))
+ panic("attempted to parse unknown event: " + p.event.typ.String())
}
}
@@ -134,19 +171,20 @@ func (p *parser) document() *node {
n := p.node(documentNode)
n.anchors = make(map[string]*node)
p.doc = n
- p.skip()
+ p.expect(yaml_DOCUMENT_START_EVENT)
n.children = append(n.children, p.parse())
- if p.event.typ != yaml_DOCUMENT_END_EVENT {
- panic("expected end of document event but got " + strconv.Itoa(int(p.event.typ)))
- }
- p.skip()
+ p.expect(yaml_DOCUMENT_END_EVENT)
return n
}
func (p *parser) alias() *node {
n := p.node(aliasNode)
n.value = string(p.event.anchor)
- p.skip()
+ n.alias = p.doc.anchors[n.value]
+ if n.alias == nil {
+ failf("unknown anchor '%s' referenced", n.value)
+ }
+ p.expect(yaml_ALIAS_EVENT)
return n
}
@@ -156,29 +194,29 @@ func (p *parser) scalar() *node {
n.tag = string(p.event.tag)
n.implicit = p.event.implicit
p.anchor(n, p.event.anchor)
- p.skip()
+ p.expect(yaml_SCALAR_EVENT)
return n
}
func (p *parser) sequence() *node {
n := p.node(sequenceNode)
p.anchor(n, p.event.anchor)
- p.skip()
- for p.event.typ != yaml_SEQUENCE_END_EVENT {
+ p.expect(yaml_SEQUENCE_START_EVENT)
+ for p.peek() != yaml_SEQUENCE_END_EVENT {
n.children = append(n.children, p.parse())
}
- p.skip()
+ p.expect(yaml_SEQUENCE_END_EVENT)
return n
}
func (p *parser) mapping() *node {
n := p.node(mappingNode)
p.anchor(n, p.event.anchor)
- p.skip()
- for p.event.typ != yaml_MAPPING_END_EVENT {
+ p.expect(yaml_MAPPING_START_EVENT)
+ for p.peek() != yaml_MAPPING_END_EVENT {
n.children = append(n.children, p.parse(), p.parse())
}
- p.skip()
+ p.expect(yaml_MAPPING_END_EVENT)
return n
}
@@ -187,7 +225,7 @@ func (p *parser) mapping() *node {
type decoder struct {
doc *node
- aliases map[string]bool
+ aliases map[*node]bool
mapType reflect.Type
terrors []string
strict bool
@@ -198,11 +236,13 @@ var (
durationType = reflect.TypeOf(time.Duration(0))
defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
ifaceType = defaultMapType.Elem()
+ timeType = reflect.TypeOf(time.Time{})
+ ptrTimeType = reflect.TypeOf(&time.Time{})
)
func newDecoder(strict bool) *decoder {
d := &decoder{mapType: defaultMapType, strict: strict}
- d.aliases = make(map[string]bool)
+ d.aliases = make(map[*node]bool)
return d
}
@@ -308,16 +348,13 @@ func (d *decoder) document(n *node, out reflect.Value) (good bool) {
}
func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
- an, ok := d.doc.anchors[n.value]
- if !ok {
- failf("unknown anchor '%s' referenced", n.value)
- }
- if d.aliases[n.value] {
+ if d.aliases[n] {
+ // TODO this could actually be allowed in some circumstances.
failf("anchor '%s' value contains itself", n.value)
}
- d.aliases[n.value] = true
- good = d.unmarshal(an, out)
- delete(d.aliases, n.value)
+ d.aliases[n] = true
+ good = d.unmarshal(n.alias, out)
+ delete(d.aliases, n)
return good
}
@@ -329,7 +366,7 @@ func resetMap(out reflect.Value) {
}
}
-func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
+func (d *decoder) scalar(n *node, out reflect.Value) bool {
var tag string
var resolved interface{}
if n.tag == "" && !n.implicit {
@@ -353,9 +390,26 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
}
return true
}
- if s, ok := resolved.(string); ok && out.CanAddr() {
- if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok {
- err := u.UnmarshalText([]byte(s))
+ 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 == yaml_BINARY_TAG {
+ 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)
}
@@ -366,46 +420,54 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
case reflect.String:
if tag == yaml_BINARY_TAG {
out.SetString(resolved.(string))
- good = true
- } else if resolved != nil {
+ return true
+ }
+ if resolved != nil {
out.SetString(n.value)
- good = true
+ return true
}
case reflect.Interface:
if resolved == nil {
out.Set(reflect.Zero(out.Type()))
+ } else if tag == yaml_TIMESTAMP_TAG {
+ // It looks like a timestamp but for backward compatibility
+ // reasons we set it as a string, so that code that unmarshals
+ // timestamp-like values into interface{} will continue to
+ // see a string and not a time.Time.
+ // TODO(v3) Drop this.
+ out.Set(reflect.ValueOf(n.value))
} else {
out.Set(reflect.ValueOf(resolved))
}
- good = true
+ return true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
switch resolved := resolved.(type) {
case int:
if !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
- good = true
+ return true
}
case int64:
if !out.OverflowInt(resolved) {
out.SetInt(resolved)
- good = true
+ return true
}
case uint64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
- good = true
+ return true
}
case float64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved))
- good = true
+ return true
}
case string:
if out.Type() == durationType {
d, err := time.ParseDuration(resolved)
if err == nil {
out.SetInt(int64(d))
- good = true
+ return true
}
}
}
@@ -414,44 +476,49 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
case int:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
- good = true
+ return true
}
case int64:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
- good = true
+ return true
}
case uint64:
if !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
- good = true
+ return true
}
case float64:
if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved))
- good = true
+ return true
}
}
case reflect.Bool:
switch resolved := resolved.(type) {
case bool:
out.SetBool(resolved)
- good = true
+ return true
}
case reflect.Float32, reflect.Float64:
switch resolved := resolved.(type) {
case int:
out.SetFloat(float64(resolved))
- good = true
+ return true
case int64:
out.SetFloat(float64(resolved))
- good = true
+ return true
case uint64:
out.SetFloat(float64(resolved))
- good = true
+ return true
case float64:
out.SetFloat(resolved)
- good = true
+ return true
+ }
+ case reflect.Struct:
+ if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
+ out.Set(resolvedv)
+ return true
}
case reflect.Ptr:
if out.Type().Elem() == reflect.TypeOf(resolved) {
@@ -459,13 +526,11 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
elem := reflect.New(out.Type().Elem())
elem.Elem().Set(reflect.ValueOf(resolved))
out.Set(elem)
- good = true
+ return true
}
}
- if !good {
- d.terror(n, tag, out)
- }
- return good
+ d.terror(n, tag, out)
+ return false
}
func settableValueOf(i interface{}) reflect.Value {
@@ -482,6 +547,10 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
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
@@ -500,7 +569,9 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
j++
}
}
- out.Set(out.Slice(0, j))
+ if out.Kind() != reflect.Array {
+ out.Set(out.Slice(0, j))
+ }
if iface.IsValid() {
iface.Set(out)
}
@@ -561,7 +632,7 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
}
e := reflect.New(et).Elem()
if d.unmarshal(n.children[i+1], e) {
- out.SetMapIndex(k, e)
+ d.setMapIndex(n.children[i+1], out, k, e)
}
}
}
@@ -569,6 +640,14 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
return true
}
+func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
+ if d.strict && out.MapIndex(k) != zeroValue {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
+ return
+ }
+ out.SetMapIndex(k, v)
+}
+
func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
outt := out.Type()
if outt.Elem() != mapItemType {
@@ -616,6 +695,10 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
elemType = inlineMap.Type().Elem()
}
+ var doneFields []bool
+ if d.strict {
+ doneFields = make([]bool, len(sinfo.FieldsList))
+ }
for i := 0; i < l; i += 2 {
ni := n.children[i]
if isMerge(ni) {
@@ -626,6 +709,13 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
continue
}
if info, ok := sinfo.FieldsMap[name.String()]; ok {
+ if d.strict {
+ if doneFields[info.Id] {
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
+ continue
+ }
+ doneFields[info.Id] = true
+ }
var field reflect.Value
if info.Inline == nil {
field = out.Field(info.Num)
@@ -639,9 +729,9 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
}
value := reflect.New(elemType).Elem()
d.unmarshal(n.children[i+1], value)
- inlineMap.SetMapIndex(name, value)
+ d.setMapIndex(n.children[i+1], inlineMap, name, value)
} else if d.strict {
- d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in struct %s", ni.line+1, name.String(), out.Type()))
+ d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
}
}
return true
diff --git a/vendor/gopkg.in/yaml.v2/decode_test.go b/vendor/gopkg.in/yaml.v2/decode_test.go
deleted file mode 100644
index e5366c261..000000000
--- a/vendor/gopkg.in/yaml.v2/decode_test.go
+++ /dev/null
@@ -1,1032 +0,0 @@
-package yaml_test
-
-import (
- "errors"
- . "gopkg.in/check.v1"
- "gopkg.in/yaml.v2"
- "math"
- "net"
- "reflect"
- "strings"
- "time"
-)
-
-var unmarshalIntTest = 123
-
-var unmarshalTests = []struct {
- data string
- value interface{}
-}{
- {
- "",
- &struct{}{},
- }, {
- "{}", &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 from spec
- {
- "canonical: y",
- map[string]interface{}{"canonical": true},
- }, {
- "answer: NO",
- map[string]interface{}{"answer": false},
- }, {
- "logical: True",
- map[string]interface{}{"logical": true},
- }, {
- "option: on",
- map[string]interface{}{"option": true},
- }, {
- "option: on",
- map[string]bool{"option": true},
- },
- // 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},
- }, {
- "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},
- }, {
- "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[interface{}]interface{}{"b": "c"}},
- },
-
- // 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: {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",
- &struct{ B int }{0},
- }, {
- "a: 1",
- &struct {
- B int "a"
- }{1},
- }, {
- "a: y",
- &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: !!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}},
- }, {
- "b: *a\na: &a {c: 1}",
- &struct {
- A, B struct {
- C int
- }
- }{struct{ C int }{1}, struct{ C int }{1}},
- },
-
- // 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}}},
- },
-
- // 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"},
- },
-
- // Duration
- {
- "a: 3s",
- map[string]time.Duration{"a": 3 * time.Second},
- },
-
- // Issue #24.
- {
- "a: <foo>",
- map[string]string{"a": "<foo>"},
- },
-
- // 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)},
- },
-
- // Ordered maps.
- {
- "{b: 2, a: 1, d: 4, c: 3, sub: {e: 5}}",
- &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
- },
-
- // Issue #39.
- {
- "a:\n b:\n c: d\n",
- map[string]struct{ B interface{} }{"a": {map[interface{}]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]net.IP{"a": net.IPv4(1, 2, 3, 4)},
- },
- {
- "a: 2015-02-24T18:19:39Z\n",
- map[string]time.Time{"a": time.Unix(1424801979, 0).In(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 🟔"},
- },
-
- // YAML Float regex shouldn't match this
- {
- "a: 123456e1\n",
- M{"a": "123456e1"},
- }, {
- "a: 123456E1\n",
- M{"a": "123456E1"},
- },
-}
-
-type M map[interface{}]interface{}
-
-type inlineB struct {
- B int
- inlineC `yaml:",inline"`
-}
-
-type inlineC struct {
- C 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()
- var value interface{}
- switch t.Kind() {
- case reflect.Map:
- value = reflect.MakeMap(t).Interface()
- case reflect.String:
- value = reflect.New(t).Interface()
- case reflect.Ptr:
- value = reflect.New(t.Elem()).Interface()
- default:
- c.Fatalf("missing case for %s", t)
- }
- err := yaml.Unmarshal([]byte(item.data), value)
- if _, ok := err.(*yaml.TypeError); !ok {
- c.Assert(err, IsNil)
- }
- if t.Kind() == reflect.String {
- c.Assert(*value.(*string), Equals, item.value)
- } else {
- c.Assert(value, DeepEquals, item.value)
- }
- }
-}
-
-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)
-}
-
-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: *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\[interface\ \{\}\]interface \{\}\{".":interface \{\}\(nil\)\}`},
- {"%TAG !%79! tag:yaml.org,2002:\n---\nv: !%79!int '1'", "yaml: did not find expected whitespace"},
-}
-
-func (s *S) TestUnmarshalErrors(c *C) {
- for _, item := range unmarshalErrorTests {
- var value interface{}
- err := yaml.Unmarshal([]byte(item.data), &value)
- c.Assert(err, ErrorMatches, item.error, Commentf("Partial unmarshal: %#v", value))
- }
-}
-
-var unmarshalerTests = []struct {
- data, tag string
- value interface{}
-}{
- {"_: {hi: there}", "!!map", map[interface{}]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(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 unmarshalerPointer struct {
- Field *unmarshalerType "_"
-}
-
-type unmarshalerValue struct {
- Field unmarshalerType "_"
-}
-
-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)
- }
- }
-}
-
-func (s *S) TestUnmarshalerValueField(c *C) {
- for _, item := range unmarshalerTests {
- obj := &unmarshalerValue{}
- 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) TestUnmarshalerWholeDocument(c *C) {
- obj := &unmarshalerType{}
- err := yaml.Unmarshal([]byte(unmarshalerTests[0].data), obj)
- c.Assert(err, IsNil)
- value, ok := obj.value.(map[interface{}]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)
-}
-
-type proxyTypeError struct{}
-
-func (v *proxyTypeError) 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) 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 failingUnmarshaler struct{}
-
-var failingErr = errors.New("failingErr")
-
-func (ft *failingUnmarshaler) UnmarshalYAML(unmarshal func(interface{}) error) error {
- return failingErr
-}
-
-func (s *S) TestUnmarshalerError(c *C) {
- err := yaml.Unmarshal([]byte("a: b"), &failingUnmarshaler{})
- c.Assert(err, Equals, failingErr)
-}
-
-type sliceUnmarshaler []int
-
-func (su *sliceUnmarshaler) 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) 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}))
-}
-
-// 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
- !<tag:yaml.org,2002:merge> "<<" : [ *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",
- }
-
- var m map[interface{}]interface{}
- err := yaml.Unmarshal([]byte(mergeTests), &m)
- c.Assert(err, IsNil)
- for name, test := range m {
- if name == "anchors" {
- 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 = []func() interface{}{
- func() interface{} { var v interface{}; v = "v"; return &v },
- func() interface{} { var s = "s"; return &s },
- func() interface{} { var s = "s"; sptr := &s; return &sptr },
- func() interface{} { var i = 1; return &i },
- func() interface{} { var i = 1; iptr := &i; return &iptr },
- func() interface{} { m := map[string]int{"s": 1}; return &m },
- func() interface{} { m := map[string]int{"s": 1}; return m },
-}
-
-func (s *S) TestUnmarshalNull(c *C) {
- for _, test := range unmarshalNullTests {
- item := test()
- zero := reflect.Zero(reflect.TypeOf(item).Elem()).Interface()
- err := yaml.Unmarshal([]byte("null"), item)
- c.Assert(err, IsNil)
- if reflect.TypeOf(item).Kind() == reflect.Map {
- c.Assert(reflect.ValueOf(item).Interface(), DeepEquals, reflect.MakeMap(reflect.TypeOf(item)).Interface())
- } else {
- c.Assert(reflect.ValueOf(item).Elem().Interface(), DeepEquals, zero)
- }
- }
-}
-
-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})
-}
-
-func (s *S) TestUnmarshalStrict(c *C) {
- v := struct{ A, B int }{}
-
- err := yaml.UnmarshalStrict([]byte("a: 1\nb: 2"), &v)
- c.Check(err, IsNil)
- err = yaml.Unmarshal([]byte("a: 1\nb: 2\nc: 3"), &v)
- c.Check(err, IsNil)
- err = yaml.UnmarshalStrict([]byte("a: 1\nb: 2\nc: 3"), &v)
- c.Check(err, ErrorMatches, "yaml: unmarshal errors:\n line 3: field c not found in struct struct { A int; B int }")
-}
-
-//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/vendor/gopkg.in/yaml.v2/emitterc.go b/vendor/gopkg.in/yaml.v2/emitterc.go
index dcaf502f0..a1c2cc526 100644
--- a/vendor/gopkg.in/yaml.v2/emitterc.go
+++ b/vendor/gopkg.in/yaml.v2/emitterc.go
@@ -2,6 +2,7 @@ package yaml
import (
"bytes"
+ "fmt"
)
// Flush the buffer if needed.
@@ -664,7 +665,7 @@ func yaml_emitter_emit_node(emitter *yaml_emitter_t, event *yaml_event_t,
return yaml_emitter_emit_mapping_start(emitter, event)
default:
return yaml_emitter_set_emitter_error(emitter,
- "expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS")
+ fmt.Sprintf("expected SCALAR, SEQUENCE-START, MAPPING-START, or ALIAS, but got %v", event.typ))
}
}
@@ -842,7 +843,7 @@ func yaml_emitter_select_scalar_style(emitter *yaml_emitter_t, event *yaml_event
return true
}
-// Write an achor.
+// Write an anchor.
func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
if emitter.anchor_data.anchor == nil {
return true
diff --git a/vendor/gopkg.in/yaml.v2/encode.go b/vendor/gopkg.in/yaml.v2/encode.go
index 84f849955..a14435e82 100644
--- a/vendor/gopkg.in/yaml.v2/encode.go
+++ b/vendor/gopkg.in/yaml.v2/encode.go
@@ -3,12 +3,14 @@ package yaml
import (
"encoding"
"fmt"
+ "io"
"reflect"
"regexp"
"sort"
"strconv"
"strings"
"time"
+ "unicode/utf8"
)
type encoder struct {
@@ -16,25 +18,39 @@ type encoder struct {
event yaml_event_t
out []byte
flow bool
+ // doneInit holds whether the initial stream_start_event has been
+ // emitted.
+ doneInit bool
}
-func newEncoder() (e *encoder) {
- e = &encoder{}
- e.must(yaml_emitter_initialize(&e.emitter))
+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)
- e.must(yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING))
- e.emit()
- e.must(yaml_document_start_event_initialize(&e.event, nil, nil, true))
- e.emit()
return e
}
-func (e *encoder) finish() {
- e.must(yaml_document_end_event_initialize(&e.event, true))
+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
+ }
+ yaml_stream_start_event_initialize(&e.event, yaml_UTF8_ENCODING)
e.emit()
+ e.doneInit = true
+}
+
+func (e *encoder) finish() {
e.emitter.open_ended = false
- e.must(yaml_stream_end_event_initialize(&e.event))
+ yaml_stream_end_event_initialize(&e.event)
e.emit()
}
@@ -44,9 +60,7 @@ func (e *encoder) destroy() {
func (e *encoder) emit() {
// This will internally delete the e.event value.
- if !yaml_emitter_emit(&e.emitter, &e.event) && e.event.typ != yaml_DOCUMENT_END_EVENT && e.event.typ != yaml_STREAM_END_EVENT {
- e.must(false)
- }
+ e.must(yaml_emitter_emit(&e.emitter, &e.event))
}
func (e *encoder) must(ok bool) {
@@ -59,13 +73,28 @@ func (e *encoder) must(ok bool) {
}
}
+func (e *encoder) marshalDoc(tag string, in reflect.Value) {
+ e.init()
+ 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) {
- if !in.IsValid() {
+ if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
e.nilv()
return
}
iface := in.Interface()
- if m, ok := iface.(Marshaler); ok {
+ switch m := iface.(type) {
+ case time.Time, *time.Time:
+ // Although time.Time implements TextMarshaler,
+ // we don't want to treat it as a string for YAML
+ // purposes because YAML has special support for
+ // timestamps.
+ case Marshaler:
v, err := m.MarshalYAML()
if err != nil {
fail(err)
@@ -75,31 +104,34 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
return
}
in = reflect.ValueOf(v)
- } else if m, ok := iface.(encoding.TextMarshaler); ok {
+ case encoding.TextMarshaler:
text, err := m.MarshalText()
if err != nil {
fail(err)
}
in = reflect.ValueOf(string(text))
+ case nil:
+ e.nilv()
+ return
}
switch in.Kind() {
case reflect.Interface:
- if in.IsNil() {
- e.nilv()
- } else {
- e.marshal(tag, in.Elem())
- }
+ e.marshal(tag, in.Elem())
case reflect.Map:
e.mapv(tag, in)
case reflect.Ptr:
- if in.IsNil() {
- e.nilv()
+ if in.Type() == ptrTimeType {
+ e.timev(tag, in.Elem())
} else {
e.marshal(tag, in.Elem())
}
case reflect.Struct:
- e.structv(tag, in)
- case reflect.Slice:
+ if in.Type() == timeType {
+ e.timev(tag, in)
+ } else {
+ e.structv(tag, in)
+ }
+ case reflect.Slice, reflect.Array:
if in.Type().Elem() == mapItemType {
e.itemsv(tag, in)
} else {
@@ -191,10 +223,10 @@ func (e *encoder) mappingv(tag string, f func()) {
e.flow = false
style = yaml_FLOW_MAPPING_STYLE
}
- e.must(yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style))
+ yaml_mapping_start_event_initialize(&e.event, nil, []byte(tag), implicit, style)
e.emit()
f()
- e.must(yaml_mapping_end_event_initialize(&e.event))
+ yaml_mapping_end_event_initialize(&e.event)
e.emit()
}
@@ -240,23 +272,36 @@ var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0
func (e *encoder) stringv(tag string, in reflect.Value) {
var style yaml_scalar_style_t
s := in.String()
- rtag, rs := resolve("", s)
- if rtag == yaml_BINARY_TAG {
- if tag == "" || tag == yaml_STR_TAG {
- tag = rtag
- s = rs.(string)
- } else if tag == yaml_BINARY_TAG {
+ canUsePlain := true
+ switch {
+ case !utf8.ValidString(s):
+ if tag == yaml_BINARY_TAG {
failf("explicitly tagged !!binary data must be base64-encoded")
- } else {
+ }
+ 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 = yaml_BINARY_TAG
+ 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 == yaml_STR_TAG && !isBase60Float(s)
}
- if tag == "" && (rtag != yaml_STR_TAG || isBase60Float(s)) {
- style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
- } else if strings.Contains(s, "\n") {
+ // 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"):
style = yaml_LITERAL_SCALAR_STYLE
- } else {
+ case canUsePlain:
style = yaml_PLAIN_SCALAR_STYLE
+ default:
+ style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
}
e.emitScalar(s, "", tag, style)
}
@@ -281,9 +326,20 @@ func (e *encoder) uintv(tag string, in reflect.Value) {
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE)
}
+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)
+}
+
func (e *encoder) floatv(tag string, in reflect.Value) {
- // FIXME: Handle 64 bits here.
- s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32)
+ // 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"
diff --git a/vendor/gopkg.in/yaml.v2/encode_test.go b/vendor/gopkg.in/yaml.v2/encode_test.go
deleted file mode 100644
index 84099bd38..000000000
--- a/vendor/gopkg.in/yaml.v2/encode_test.go
+++ /dev/null
@@ -1,501 +0,0 @@
-package yaml_test
-
-import (
- "fmt"
- "math"
- "strconv"
- "strings"
- "time"
-
- . "gopkg.in/check.v1"
- "gopkg.in/yaml.v2"
- "net"
- "os"
-)
-
-var marshalIntTest = 123
-
-var marshalTests = []struct {
- value interface{}
- data string
-}{
- {
- 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": -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 {
- B int "a"
- }{1},
- "a: 1\n",
- }, {
- &struct{ A bool }{true},
- "a: true\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",
- },
-
- // 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",
- },
-
- // 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",
- },
-
- // 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": "<foo>"},
- "a: <foo>\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",
- },
-
- // Ordered maps.
- {
- &yaml.MapSlice{{"b", 2}, {"a", 1}, {"d", 4}, {"c", 3}, {"sub", yaml.MapSlice{{"e", 5}}}},
- "b: 2\na: 1\nd: 4\nc: 3\nsub:\n e: 5\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",
- },
- {
- map[string]time.Time{"a": time.Unix(1424801979, 0)},
- "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",
- },
-}
-
-func (s *S) TestMarshal(c *C) {
- defer os.Setenv("TZ", os.Getenv("TZ"))
- os.Setenv("TZ", "UTC")
- for _, item := range marshalTests {
- data, err := yaml.Marshal(item.value)
- c.Assert(err, IsNil)
- c.Assert(string(data), Equals, item.data)
- }
-}
-
-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: `Can't 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) 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/2",
- "a/10",
- "a~10",
- "ab/1",
- "b/1",
- "b/01",
- "b/2",
- "b/02",
- "b/3",
- "b/03",
- "b1",
- "b01",
- "b3",
- "c2.10",
- "c10.2",
- "d1",
- "d12",
- "d12a",
- }
- 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
- }
-}
diff --git a/vendor/gopkg.in/yaml.v2/example_embedded_test.go b/vendor/gopkg.in/yaml.v2/example_embedded_test.go
deleted file mode 100644
index 171c0931a..000000000
--- a/vendor/gopkg.in/yaml.v2/example_embedded_test.go
+++ /dev/null
@@ -1,41 +0,0 @@
-package yaml_test
-
-import (
- "fmt"
- "log"
-
- "gopkg.in/yaml.v2"
-)
-
-// 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/vendor/gopkg.in/yaml.v2/go.mod b/vendor/gopkg.in/yaml.v2/go.mod
new file mode 100644
index 000000000..1934e8769
--- /dev/null
+++ b/vendor/gopkg.in/yaml.v2/go.mod
@@ -0,0 +1,5 @@
+module "gopkg.in/yaml.v2"
+
+require (
+ "gopkg.in/check.v1" v0.0.0-20161208181325-20d25e280405
+)
diff --git a/vendor/gopkg.in/yaml.v2/readerc.go b/vendor/gopkg.in/yaml.v2/readerc.go
index f45079171..7c1f5fac3 100644
--- a/vendor/gopkg.in/yaml.v2/readerc.go
+++ b/vendor/gopkg.in/yaml.v2/readerc.go
@@ -93,9 +93,18 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
panic("read handler must be set")
}
+ // [Go] This function was changed to guarantee the requested length size at EOF.
+ // The fact we need to do this is pretty awful, but the description above implies
+ // for that to be the case, and there are tests
+
// If the EOF flag is set and the raw buffer is empty, do nothing.
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) {
- return true
+ // [Go] ACTUALLY! Read the documentation of this function above.
+ // This is just broken. To return true, we need to have the
+ // given length in the buffer. Not doing that means every single
+ // check that calls this function to make sure the buffer has a
+ // given length is Go) panicking; or C) accessing invalid memory.
+ //return true
}
// Return if the buffer contains enough characters.
@@ -389,6 +398,15 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
break
}
}
+ // [Go] Read the documentation of this function above. To return true,
+ // we need to have the given length in the buffer. Not doing that means
+ // every single check that calls this function to make sure the buffer
+ // has a given length is Go) panicking; or C) accessing invalid memory.
+ // This happens here due to the EOF above breaking early.
+ for buffer_len < length {
+ parser.buffer[buffer_len] = 0
+ buffer_len++
+ }
parser.buffer = parser.buffer[:buffer_len]
return true
}
diff --git a/vendor/gopkg.in/yaml.v2/resolve.go b/vendor/gopkg.in/yaml.v2/resolve.go
index 232313cc0..6c151db6f 100644
--- a/vendor/gopkg.in/yaml.v2/resolve.go
+++ b/vendor/gopkg.in/yaml.v2/resolve.go
@@ -6,7 +6,7 @@ import (
"regexp"
"strconv"
"strings"
- "unicode/utf8"
+ "time"
)
type resolveMapItem struct {
@@ -75,7 +75,7 @@ func longTag(tag string) string {
func resolvableTag(tag string) bool {
switch tag {
- case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG:
+ case "", yaml_STR_TAG, yaml_BOOL_TAG, yaml_INT_TAG, yaml_FLOAT_TAG, yaml_NULL_TAG, yaml_TIMESTAMP_TAG:
return true
}
return false
@@ -92,6 +92,19 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
switch tag {
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
return
+ case yaml_FLOAT_TAG:
+ if rtag == yaml_INT_TAG {
+ switch v := out.(type) {
+ case int64:
+ rtag = yaml_FLOAT_TAG
+ out = float64(v)
+ return
+ case int:
+ rtag = yaml_FLOAT_TAG
+ out = float64(v)
+ return
+ }
+ }
}
failf("cannot decode %s `%s` as a %s", shortTag(rtag), in, shortTag(tag))
}()
@@ -125,6 +138,15 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
case 'D', 'S':
// Int, float, or timestamp.
+ // Only try values as a timestamp if the value is unquoted or there's an explicit
+ // !!timestamp tag.
+ if tag == "" || tag == yaml_TIMESTAMP_TAG {
+ t, ok := parseTimestamp(in)
+ if ok {
+ return yaml_TIMESTAMP_TAG, t
+ }
+ }
+
plain := strings.Replace(in, "_", "", -1)
intv, err := strconv.ParseInt(plain, 0, 64)
if err == nil {
@@ -158,28 +180,20 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
return yaml_INT_TAG, uintv
}
} else if strings.HasPrefix(plain, "-0b") {
- intv, err := strconv.ParseInt(plain[3:], 2, 64)
+ intv, err := strconv.ParseInt("-" + plain[3:], 2, 64)
if err == nil {
- if intv == int64(int(intv)) {
- return yaml_INT_TAG, -int(intv)
+ if true || intv == int64(int(intv)) {
+ return yaml_INT_TAG, int(intv)
} else {
- return yaml_INT_TAG, -intv
+ return yaml_INT_TAG, intv
}
}
}
- // XXX Handle timestamps here.
-
default:
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")")
}
}
- if tag == yaml_BINARY_TAG {
- return yaml_BINARY_TAG, in
- }
- if utf8.ValidString(in) {
- return yaml_STR_TAG, in
- }
- return yaml_BINARY_TAG, encodeBase64(in)
+ return yaml_STR_TAG, in
}
// encodeBase64 encodes s as base64 that is broken up into multiple lines
@@ -206,3 +220,39 @@ func encodeBase64(s string) string {
}
return string(out[:k])
}
+
+// This is a subset of the formats allowed by the regular expression
+// defined at http://yaml.org/type/timestamp.html.
+var allowedTimestampFormats = []string{
+ "2006-1-2T15:4:5.999999999Z07:00", // RCF3339Nano with short date fields.
+ "2006-1-2t15:4:5.999999999Z07:00", // RFC3339Nano with short date fields and lower-case "t".
+ "2006-1-2 15:4:5.999999999", // space separated with no time zone
+ "2006-1-2", // date only
+ // Notable exception: time.Parse cannot handle: "2001-12-14 21:59:43.10 -5"
+ // from the set of examples.
+}
+
+// parseTimestamp parses s as a timestamp string and
+// returns the timestamp and reports whether it succeeded.
+// Timestamp formats are defined at http://yaml.org/type/timestamp.html
+func parseTimestamp(s string) (time.Time, bool) {
+ // TODO write code to check all the formats supported by
+ // http://yaml.org/type/timestamp.html instead of using time.Parse.
+
+ // Quick check: all date formats start with YYYY-.
+ i := 0
+ for ; i < len(s); i++ {
+ if c := s[i]; c < '0' || c > '9' {
+ break
+ }
+ }
+ if i != 4 || i == len(s) || s[i] != '-' {
+ return time.Time{}, false
+ }
+ for _, format := range allowedTimestampFormats {
+ if t, err := time.Parse(format, s); err == nil {
+ return t, true
+ }
+ }
+ return time.Time{}, false
+}
diff --git a/vendor/gopkg.in/yaml.v2/scannerc.go b/vendor/gopkg.in/yaml.v2/scannerc.go
index 074484455..077fd1dd2 100644
--- a/vendor/gopkg.in/yaml.v2/scannerc.go
+++ b/vendor/gopkg.in/yaml.v2/scannerc.go
@@ -871,12 +871,6 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
required := parser.flow_level == 0 && parser.indent == parser.mark.column
- // A simple key is required only when it is the first token in the current
- // line. Therefore it is always allowed. But we add a check anyway.
- if required && !parser.simple_key_allowed {
- panic("should not happen")
- }
-
//
// If the current position may start a simple key, save it.
//
@@ -2475,6 +2469,10 @@ func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, si
}
}
+ if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
+ return false
+ }
+
// Check if we are at the end of the scalar.
if single {
if parser.buffer[parser.buffer_pos] == '\'' {
@@ -2487,10 +2485,6 @@ func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, si
}
// Consume blank characters.
- if parser.unread < 1 && !yaml_parser_update_buffer(parser, 1) {
- return false
- }
-
for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
if is_blank(parser.buffer, parser.buffer_pos) {
// Consume a space or a tab character.
@@ -2592,19 +2586,10 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b
// Consume non-blank characters.
for !is_blankz(parser.buffer, parser.buffer_pos) {
- // Check for 'x:x' in the flow context. TODO: Fix the test "spec-08-13".
- if parser.flow_level > 0 &&
- parser.buffer[parser.buffer_pos] == ':' &&
- !is_blankz(parser.buffer, parser.buffer_pos+1) {
- yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
- start_mark, "found unexpected ':'")
- return false
- }
-
// Check for indicators that may end a plain scalar.
if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
(parser.flow_level > 0 &&
- (parser.buffer[parser.buffer_pos] == ',' || parser.buffer[parser.buffer_pos] == ':' ||
+ (parser.buffer[parser.buffer_pos] == ',' ||
parser.buffer[parser.buffer_pos] == '?' || parser.buffer[parser.buffer_pos] == '[' ||
parser.buffer[parser.buffer_pos] == ']' || parser.buffer[parser.buffer_pos] == '{' ||
parser.buffer[parser.buffer_pos] == '}')) {
@@ -2656,10 +2641,10 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b
for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
if is_blank(parser.buffer, parser.buffer_pos) {
- // Check for tab character that abuse indentation.
+ // Check for tab characters that abuse indentation.
if leading_blanks && parser.mark.column < indent && is_tab(parser.buffer, parser.buffer_pos) {
yaml_parser_set_scanner_error(parser, "while scanning a plain scalar",
- start_mark, "found a tab character that violate indentation")
+ start_mark, "found a tab character that violates indentation")
return false
}
diff --git a/vendor/gopkg.in/yaml.v2/sorter.go b/vendor/gopkg.in/yaml.v2/sorter.go
index 5958822f9..4c45e660a 100644
--- a/vendor/gopkg.in/yaml.v2/sorter.go
+++ b/vendor/gopkg.in/yaml.v2/sorter.go
@@ -51,6 +51,15 @@ func (l keyList) Less(i, j int) bool {
}
var ai, bi int
var an, bn int64
+ if ar[i] == '0' || br[i] == '0' {
+ for j := i-1; j >= 0 && unicode.IsDigit(ar[j]); j-- {
+ if ar[j] != '0' {
+ an = 1
+ bn = 1
+ break
+ }
+ }
+ }
for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
an = an*10 + int64(ar[ai]-'0')
}
diff --git a/vendor/gopkg.in/yaml.v2/suite_test.go b/vendor/gopkg.in/yaml.v2/suite_test.go
deleted file mode 100644
index c5cf1ed4f..000000000
--- a/vendor/gopkg.in/yaml.v2/suite_test.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package yaml_test
-
-import (
- . "gopkg.in/check.v1"
- "testing"
-)
-
-func Test(t *testing.T) { TestingT(t) }
-
-type S struct{}
-
-var _ = Suite(&S{})
diff --git a/vendor/gopkg.in/yaml.v2/writerc.go b/vendor/gopkg.in/yaml.v2/writerc.go
index 190362f25..a2dde608c 100644
--- a/vendor/gopkg.in/yaml.v2/writerc.go
+++ b/vendor/gopkg.in/yaml.v2/writerc.go
@@ -18,72 +18,9 @@ func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
return true
}
- // If the output encoding is UTF-8, we don't need to recode the buffer.
- if emitter.encoding == yaml_UTF8_ENCODING {
- if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
- return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
- }
- emitter.buffer_pos = 0
- return true
- }
-
- // Recode the buffer into the raw buffer.
- var low, high int
- if emitter.encoding == yaml_UTF16LE_ENCODING {
- low, high = 0, 1
- } else {
- high, low = 1, 0
- }
-
- pos := 0
- for pos < emitter.buffer_pos {
- // See the "reader.c" code for more details on UTF-8 encoding. Note
- // that we assume that the buffer contains a valid UTF-8 sequence.
-
- // Read the next UTF-8 character.
- octet := emitter.buffer[pos]
-
- var w int
- var value rune
- switch {
- case octet&0x80 == 0x00:
- w, value = 1, rune(octet&0x7F)
- case octet&0xE0 == 0xC0:
- w, value = 2, rune(octet&0x1F)
- case octet&0xF0 == 0xE0:
- w, value = 3, rune(octet&0x0F)
- case octet&0xF8 == 0xF0:
- w, value = 4, rune(octet&0x07)
- }
- for k := 1; k < w; k++ {
- octet = emitter.buffer[pos+k]
- value = (value << 6) + (rune(octet) & 0x3F)
- }
- pos += w
-
- // Write the character.
- if value < 0x10000 {
- var b [2]byte
- b[high] = byte(value >> 8)
- b[low] = byte(value & 0xFF)
- emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1])
- } else {
- // Write the character using a surrogate pair (check "reader.c").
- var b [4]byte
- value -= 0x10000
- b[high] = byte(0xD8 + (value >> 18))
- b[low] = byte((value >> 10) & 0xFF)
- b[high+2] = byte(0xDC + ((value >> 8) & 0xFF))
- b[low+2] = byte(value & 0xFF)
- emitter.raw_buffer = append(emitter.raw_buffer, b[0], b[1], b[2], b[3])
- }
- }
-
- // Write the raw buffer.
- if err := emitter.write_handler(emitter, emitter.raw_buffer); err != nil {
+ if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
}
emitter.buffer_pos = 0
- emitter.raw_buffer = emitter.raw_buffer[:0]
return true
}
diff --git a/vendor/gopkg.in/yaml.v2/yaml.go b/vendor/gopkg.in/yaml.v2/yaml.go
index 5e3c2daee..de85aa4cd 100644
--- a/vendor/gopkg.in/yaml.v2/yaml.go
+++ b/vendor/gopkg.in/yaml.v2/yaml.go
@@ -9,6 +9,7 @@ package yaml
import (
"errors"
"fmt"
+ "io"
"reflect"
"strings"
"sync"
@@ -81,12 +82,58 @@ func Unmarshal(in []byte, out interface{}) (err error) {
}
// UnmarshalStrict is like Unmarshal except that any fields that are found
-// in the data that do not have corresponding struct members will result in
+// in the data that do not have corresponding struct members, or mapping
+// keys that are duplicates, will result in
// an error.
func UnmarshalStrict(in []byte, out interface{}) (err error) {
return unmarshal(in, out, true)
}
+// A Decorder reads and decodes YAML values from an input stream.
+type Decoder struct {
+ strict bool
+ parser *parser
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may read
+// data from r beyond the YAML values requested.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{
+ parser: newParserFromReader(r),
+ }
+}
+
+// SetStrict sets whether strict decoding behaviour is enabled when
+// decoding items in the data (see UnmarshalStrict). By default, decoding is not strict.
+func (dec *Decoder) SetStrict(strict bool) {
+ dec.strict = strict
+}
+
+// Decode reads the next YAML-encoded value from its input
+// and stores it in the value pointed to by v.
+//
+// See the documentation for Unmarshal for details about the
+// conversion of YAML into a Go value.
+func (dec *Decoder) Decode(v interface{}) (err error) {
+ d := newDecoder(dec.strict)
+ defer handleErr(&err)
+ node := dec.parser.parse()
+ if node == nil {
+ return io.EOF
+ }
+ out := reflect.ValueOf(v)
+ if out.Kind() == reflect.Ptr && !out.IsNil() {
+ out = out.Elem()
+ }
+ d.unmarshal(node, out)
+ if len(d.terrors) > 0 {
+ return &TypeError{d.terrors}
+ }
+ return nil
+}
+
func unmarshal(in []byte, out interface{}, strict bool) (err error) {
defer handleErr(&err)
d := newDecoder(strict)
@@ -110,8 +157,8 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
// of the generated document will reflect the structure of the value itself.
// Maps and pointers (to struct, string, int, etc) are accepted as the in value.
//
-// Struct fields are only unmarshalled if they are exported (have an upper case
-// first letter), and are unmarshalled using the field name lowercased as the
+// Struct fields are only marshalled if they are exported (have an upper case
+// first letter), and are marshalled using the field name lowercased as the
// default key. Custom keys may be defined via the "yaml" name in the field
// tag: the content preceding the first comma is used as the key, and the
// following comma-separated options are used to tweak the marshalling process.
@@ -125,7 +172,10 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
//
// omitempty Only include the field if it's not set to the zero
// value for the type or to empty slices or maps.
-// Does not apply to zero valued structs.
+// Zero valued structs will be omitted if all their public
+// fields are zero, unless they implement an IsZero
+// method (see the IsZeroer interface type), in which
+// case the field will be included if that method returns true.
//
// flow Marshal using a flow style (useful for structs,
// sequences and maps).
@@ -150,12 +200,47 @@ func Marshal(in interface{}) (out []byte, err error) {
defer handleErr(&err)
e := newEncoder()
defer e.destroy()
- e.marshal("", reflect.ValueOf(in))
+ e.marshalDoc("", reflect.ValueOf(in))
e.finish()
out = e.out
return
}
+// An Encoder writes YAML values to an output stream.
+type Encoder struct {
+ encoder *encoder
+}
+
+// NewEncoder returns a new encoder that writes to w.
+// The Encoder should be closed after use to flush all data
+// to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{
+ encoder: newEncoderWithWriter(w),
+ }
+}
+
+// Encode writes the YAML encoding of v to the stream.
+// If multiple items are encoded to the stream, the
+// second and subsequent document will be preceded
+// with a "---" document separator, but the first will not.
+//
+// See the documentation for Marshal for details about the conversion of Go
+// values to YAML.
+func (e *Encoder) Encode(v interface{}) (err error) {
+ defer handleErr(&err)
+ e.encoder.marshalDoc("", reflect.ValueOf(v))
+ return nil
+}
+
+// Close closes the encoder by writing any remaining data.
+// It does not write a stream terminating string "...".
+func (e *Encoder) Close() (err error) {
+ defer handleErr(&err)
+ e.encoder.finish()
+ return nil
+}
+
func handleErr(err *error) {
if v := recover(); v != nil {
if e, ok := v.(yamlError); ok {
@@ -211,6 +296,9 @@ type fieldInfo struct {
Num int
OmitEmpty bool
Flow bool
+ // Id holds the unique field identifier, so we can cheaply
+ // check for field duplicates without maintaining an extra map.
+ Id int
// Inline holds the field index if the field is part of an inlined struct.
Inline []int
@@ -290,6 +378,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
} else {
finfo.Inline = append([]int{i}, finfo.Inline...)
}
+ finfo.Id = len(fieldsList)
fieldsMap[finfo.Key] = finfo
fieldsList = append(fieldsList, finfo)
}
@@ -311,11 +400,16 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
return nil, errors.New(msg)
}
+ info.Id = len(fieldsList)
fieldsList = append(fieldsList, info)
fieldsMap[info.Key] = info
}
- sinfo = &structInfo{fieldsMap, fieldsList, inlineMap}
+ sinfo = &structInfo{
+ FieldsMap: fieldsMap,
+ FieldsList: fieldsList,
+ InlineMap: inlineMap,
+ }
fieldMapMutex.Lock()
structMap[st] = sinfo
@@ -323,8 +417,23 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
return sinfo, nil
}
+// IsZeroer is used to check whether an object is zero to
+// determine whether it should be omitted when marshaling
+// with the omitempty flag. One notable implementation
+// is time.Time.
+type IsZeroer interface {
+ IsZero() bool
+}
+
func isZero(v reflect.Value) bool {
- switch v.Kind() {
+ kind := v.Kind()
+ if z, ok := v.Interface().(IsZeroer); ok {
+ if (kind == reflect.Ptr || kind == reflect.Interface) && v.IsNil() {
+ return true
+ }
+ return z.IsZero()
+ }
+ switch kind {
case reflect.String:
return len(v.String()) == 0
case reflect.Interface, reflect.Ptr:
diff --git a/vendor/gopkg.in/yaml.v2/yamlh.go b/vendor/gopkg.in/yaml.v2/yamlh.go
index 3caeca049..e25cee563 100644
--- a/vendor/gopkg.in/yaml.v2/yamlh.go
+++ b/vendor/gopkg.in/yaml.v2/yamlh.go
@@ -1,6 +1,7 @@
package yaml
import (
+ "fmt"
"io"
)
@@ -239,6 +240,27 @@ const (
yaml_MAPPING_END_EVENT // A MAPPING-END event.
)
+var eventStrings = []string{
+ yaml_NO_EVENT: "none",
+ yaml_STREAM_START_EVENT: "stream start",
+ yaml_STREAM_END_EVENT: "stream end",
+ yaml_DOCUMENT_START_EVENT: "document start",
+ yaml_DOCUMENT_END_EVENT: "document end",
+ yaml_ALIAS_EVENT: "alias",
+ yaml_SCALAR_EVENT: "scalar",
+ yaml_SEQUENCE_START_EVENT: "sequence start",
+ yaml_SEQUENCE_END_EVENT: "sequence end",
+ yaml_MAPPING_START_EVENT: "mapping start",
+ yaml_MAPPING_END_EVENT: "mapping end",
+}
+
+func (e yaml_event_type_t) String() string {
+ if e < 0 || int(e) >= len(eventStrings) {
+ return fmt.Sprintf("unknown event %d", e)
+ }
+ return eventStrings[e]
+}
+
// The event structure.
type yaml_event_t struct {
@@ -521,9 +543,9 @@ type yaml_parser_t struct {
read_handler yaml_read_handler_t // Read handler.
- input_file io.Reader // File input data.
- input []byte // String input data.
- input_pos int
+ input_reader io.Reader // File input data.
+ input []byte // String input data.
+ input_pos int
eof bool // EOF flag
@@ -632,7 +654,7 @@ type yaml_emitter_t struct {
write_handler yaml_write_handler_t // Write handler.
output_buffer *[]byte // String output data.
- output_file io.Writer // File output data.
+ output_writer io.Writer // File output data.
buffer []byte // The working buffer.
buffer_pos int // The current position of the buffer.