Update gopkg.in/yaml.v2 indirect dependency to v2.4.0

This commit is contained in:
Cameron Moore 2024-03-29 13:33:17 -05:00
parent 853030346b
commit 16c49415ab
No known key found for this signature in database
GPG key ID: AF96E12468D7553E
17 changed files with 733 additions and 336 deletions

2
go.mod
View file

@ -17,5 +17,5 @@ require (
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/kr/pretty v0.1.0 // indirect github.com/kr/pretty v0.1.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )

5
go.sum
View file

@ -22,7 +22,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7 h1:+t9dhfO+GNOIGJof6kPOAenx7YgrZMTdRPV+EsnPabk= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

16
vendor/gopkg.in/yaml.v2/.travis.yml generated vendored
View file

@ -1,9 +1,17 @@
language: go language: go
go: go:
- 1.4 - "1.4.x"
- 1.5 - "1.5.x"
- 1.6 - "1.6.x"
- tip - "1.7.x"
- "1.8.x"
- "1.9.x"
- "1.10.x"
- "1.11.x"
- "1.12.x"
- "1.13.x"
- "1.14.x"
- "tip"
go_import_path: gopkg.in/yaml.v2 go_import_path: gopkg.in/yaml.v2

13
vendor/gopkg.in/yaml.v2/NOTICE generated vendored Normal file
View file

@ -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.

4
vendor/gopkg.in/yaml.v2/README.md generated vendored
View file

@ -48,8 +48,6 @@ The yaml package is licensed under the Apache License 2.0. Please see the LICENS
Example Example
------- -------
Some more examples can be found in the "examples" folder.
```Go ```Go
package main package main
@ -67,6 +65,8 @@ b:
d: [3, 4] d: [3, 4]
` `
// Note: struct fields must be public in order for unmarshal to
// correctly populate the data.
type T struct { type T struct {
A string A string
B struct { B struct {

60
vendor/gopkg.in/yaml.v2/apic.go generated vendored
View file

@ -2,7 +2,6 @@ package yaml
import ( import (
"io" "io"
"os"
) )
func yaml_insert_token(parser *yaml_parser_t, pos int, token *yaml_token_t) { 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 return n, nil
} }
// File read handler. // Reader read handler.
func yaml_file_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) { func yaml_reader_read_handler(parser *yaml_parser_t, buffer []byte) (n int, err error) {
return parser.input_file.Read(buffer) return parser.input_reader.Read(buffer)
} }
// Set a string input. // Set a string input.
@ -64,12 +63,12 @@ func yaml_parser_set_input_string(parser *yaml_parser_t, input []byte) {
} }
// Set a file input. // 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 { if parser.read_handler != nil {
panic("must set the input source only once") panic("must set the input source only once")
} }
parser.read_handler = yaml_file_read_handler parser.read_handler = yaml_reader_read_handler
parser.input_file = file parser.input_reader = r
} }
// Set the source encoding. // Set the source encoding.
@ -80,15 +79,19 @@ func yaml_parser_set_encoding(parser *yaml_parser_t, encoding yaml_encoding_t) {
parser.encoding = encoding parser.encoding = encoding
} }
var disableLineWrapping = false
// Create a new emitter object. // 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{ *emitter = yaml_emitter_t{
buffer: make([]byte, output_buffer_size), buffer: make([]byte, output_buffer_size),
raw_buffer: make([]byte, 0, output_raw_buffer_size), raw_buffer: make([]byte, 0, output_raw_buffer_size),
states: make([]yaml_emitter_state_t, 0, initial_stack_size), states: make([]yaml_emitter_state_t, 0, initial_stack_size),
events: make([]yaml_event_t, 0, initial_queue_size), events: make([]yaml_event_t, 0, initial_queue_size),
} }
return true if disableLineWrapping {
emitter.best_width = -1
}
} }
// Destroy an emitter object. // Destroy an emitter object.
@ -102,9 +105,10 @@ func yaml_string_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
return nil return nil
} }
// File write handler. // yaml_writer_write_handler uses emitter.output_writer to write the
func yaml_file_write_handler(emitter *yaml_emitter_t, buffer []byte) error { // emitted text.
_, err := emitter.output_file.Write(buffer) func yaml_writer_write_handler(emitter *yaml_emitter_t, buffer []byte) error {
_, err := emitter.output_writer.Write(buffer)
return err return err
} }
@ -118,12 +122,12 @@ func yaml_emitter_set_output_string(emitter *yaml_emitter_t, output_buffer *[]by
} }
// Set a file output. // 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 { if emitter.write_handler != nil {
panic("must set the output target only once") panic("must set the output target only once")
} }
emitter.write_handler = yaml_file_write_handler emitter.write_handler = yaml_writer_write_handler
emitter.output_file = file emitter.output_writer = w
} }
// Set the output encoding. // Set the output encoding.
@ -252,41 +256,41 @@ func yaml_emitter_set_break(emitter *yaml_emitter_t, line_break yaml_break_t) {
// //
// Create STREAM-START. // 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{ *event = yaml_event_t{
typ: yaml_STREAM_START_EVENT, typ: yaml_STREAM_START_EVENT,
encoding: encoding, encoding: encoding,
} }
return true
} }
// Create STREAM-END. // 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{ *event = yaml_event_t{
typ: yaml_STREAM_END_EVENT, typ: yaml_STREAM_END_EVENT,
} }
return true
} }
// Create DOCUMENT-START. // Create DOCUMENT-START.
func yaml_document_start_event_initialize(event *yaml_event_t, version_directive *yaml_version_directive_t, func yaml_document_start_event_initialize(
tag_directives []yaml_tag_directive_t, implicit bool) bool { event *yaml_event_t,
version_directive *yaml_version_directive_t,
tag_directives []yaml_tag_directive_t,
implicit bool,
) {
*event = yaml_event_t{ *event = yaml_event_t{
typ: yaml_DOCUMENT_START_EVENT, typ: yaml_DOCUMENT_START_EVENT,
version_directive: version_directive, version_directive: version_directive,
tag_directives: tag_directives, tag_directives: tag_directives,
implicit: implicit, implicit: implicit,
} }
return true
} }
// Create DOCUMENT-END. // 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{ *event = yaml_event_t{
typ: yaml_DOCUMENT_END_EVENT, typ: yaml_DOCUMENT_END_EVENT,
implicit: implicit, implicit: implicit,
} }
return true
} }
///* ///*
@ -348,7 +352,7 @@ func yaml_sequence_end_event_initialize(event *yaml_event_t) bool {
} }
// Create MAPPING-START. // 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{ *event = yaml_event_t{
typ: yaml_MAPPING_START_EVENT, typ: yaml_MAPPING_START_EVENT,
anchor: anchor, anchor: anchor,
@ -356,15 +360,13 @@ func yaml_mapping_start_event_initialize(event *yaml_event_t, anchor, tag []byte
implicit: implicit, implicit: implicit,
style: yaml_style_t(style), style: yaml_style_t(style),
} }
return true
} }
// Create MAPPING-END. // 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{ *event = yaml_event_t{
typ: yaml_MAPPING_END_EVENT, typ: yaml_MAPPING_END_EVENT,
} }
return true
} }
// Destroy an event object. // Destroy an event object.
@ -471,7 +473,7 @@ func yaml_event_delete(event *yaml_event_t) {
// } context // } context
// tag_directive *yaml_tag_directive_t // 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. // assert(document) // Non-NULL document object is expected.
// //

268
vendor/gopkg.in/yaml.v2/decode.go generated vendored
View file

@ -4,6 +4,7 @@ import (
"encoding" "encoding"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"io"
"math" "math"
"reflect" "reflect"
"strconv" "strconv"
@ -22,6 +23,8 @@ type node struct {
kind int kind int
line, column int line, column int
tag string tag string
// For an alias node, alias holds the resolved alias.
alias *node
value string value string
implicit bool implicit bool
children []*node children []*node
@ -35,6 +38,7 @@ type parser struct {
parser yaml_parser_t parser yaml_parser_t
event yaml_event_t event yaml_event_t
doc *node doc *node
doneInit bool
} }
func newParser(b []byte) *parser { func newParser(b []byte) *parser {
@ -42,21 +46,30 @@ func newParser(b []byte) *parser {
if !yaml_parser_initialize(&p.parser) { if !yaml_parser_initialize(&p.parser) {
panic("failed to initialize YAML emitter") panic("failed to initialize YAML emitter")
} }
if len(b) == 0 { if len(b) == 0 {
b = []byte{'\n'} b = []byte{'\n'}
} }
yaml_parser_set_input_string(&p.parser, b) yaml_parser_set_input_string(&p.parser, b)
p.skip()
if p.event.typ != yaml_STREAM_START_EVENT {
panic("expected stream start event, got " + strconv.Itoa(int(p.event.typ)))
}
p.skip()
return &p 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.expect(yaml_STREAM_START_EVENT)
p.doneInit = true
}
func (p *parser) destroy() { func (p *parser) destroy() {
if p.event.typ != yaml_NO_EVENT { if p.event.typ != yaml_NO_EVENT {
yaml_event_delete(&p.event) yaml_event_delete(&p.event)
@ -64,16 +77,35 @@ func (p *parser) destroy() {
yaml_parser_delete(&p.parser) yaml_parser_delete(&p.parser)
} }
func (p *parser) skip() { // expect consumes an event from the event stream and
if p.event.typ != yaml_NO_EVENT { // 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 { if p.event.typ == yaml_STREAM_END_EVENT {
failf("attempted to go past the end of stream; corrupted value?") 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) 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) { if !yaml_parser_parse(&p.parser, &p.event) {
p.fail() p.fail()
} }
return p.event.typ
} }
func (p *parser) fail() { func (p *parser) fail() {
@ -81,6 +113,10 @@ func (p *parser) fail() {
var line int var line int
if p.parser.problem_mark.line != 0 { if p.parser.problem_mark.line != 0 {
line = p.parser.problem_mark.line 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 { } else if p.parser.context_mark.line != 0 {
line = p.parser.context_mark.line line = p.parser.context_mark.line
} }
@ -103,7 +139,8 @@ func (p *parser) anchor(n *node, anchor []byte) {
} }
func (p *parser) parse() *node { func (p *parser) parse() *node {
switch p.event.typ { p.init()
switch p.peek() {
case yaml_SCALAR_EVENT: case yaml_SCALAR_EVENT:
return p.scalar() return p.scalar()
case yaml_ALIAS_EVENT: case yaml_ALIAS_EVENT:
@ -118,7 +155,7 @@ func (p *parser) parse() *node {
// Happens when attempting to decode an empty buffer. // Happens when attempting to decode an empty buffer.
return nil return nil
default: 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 := p.node(documentNode)
n.anchors = make(map[string]*node) n.anchors = make(map[string]*node)
p.doc = n p.doc = n
p.skip() p.expect(yaml_DOCUMENT_START_EVENT)
n.children = append(n.children, p.parse()) n.children = append(n.children, p.parse())
if p.event.typ != yaml_DOCUMENT_END_EVENT { p.expect(yaml_DOCUMENT_END_EVENT)
panic("expected end of document event but got " + strconv.Itoa(int(p.event.typ)))
}
p.skip()
return n return n
} }
func (p *parser) alias() *node { func (p *parser) alias() *node {
n := p.node(aliasNode) n := p.node(aliasNode)
n.value = string(p.event.anchor) 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 return n
} }
@ -156,29 +194,29 @@ func (p *parser) scalar() *node {
n.tag = string(p.event.tag) n.tag = string(p.event.tag)
n.implicit = p.event.implicit n.implicit = p.event.implicit
p.anchor(n, p.event.anchor) p.anchor(n, p.event.anchor)
p.skip() p.expect(yaml_SCALAR_EVENT)
return n return n
} }
func (p *parser) sequence() *node { func (p *parser) sequence() *node {
n := p.node(sequenceNode) n := p.node(sequenceNode)
p.anchor(n, p.event.anchor) p.anchor(n, p.event.anchor)
p.skip() p.expect(yaml_SEQUENCE_START_EVENT)
for p.event.typ != yaml_SEQUENCE_END_EVENT { for p.peek() != yaml_SEQUENCE_END_EVENT {
n.children = append(n.children, p.parse()) n.children = append(n.children, p.parse())
} }
p.skip() p.expect(yaml_SEQUENCE_END_EVENT)
return n return n
} }
func (p *parser) mapping() *node { func (p *parser) mapping() *node {
n := p.node(mappingNode) n := p.node(mappingNode)
p.anchor(n, p.event.anchor) p.anchor(n, p.event.anchor)
p.skip() p.expect(yaml_MAPPING_START_EVENT)
for p.event.typ != yaml_MAPPING_END_EVENT { for p.peek() != yaml_MAPPING_END_EVENT {
n.children = append(n.children, p.parse(), p.parse()) n.children = append(n.children, p.parse(), p.parse())
} }
p.skip() p.expect(yaml_MAPPING_END_EVENT)
return n return n
} }
@ -187,10 +225,14 @@ func (p *parser) mapping() *node {
type decoder struct { type decoder struct {
doc *node doc *node
aliases map[string]bool aliases map[*node]bool
mapType reflect.Type mapType reflect.Type
terrors []string terrors []string
strict bool strict bool
decodeCount int
aliasCount int
aliasDepth int
} }
var ( var (
@ -198,11 +240,13 @@ var (
durationType = reflect.TypeOf(time.Duration(0)) durationType = reflect.TypeOf(time.Duration(0))
defaultMapType = reflect.TypeOf(map[interface{}]interface{}{}) defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
ifaceType = defaultMapType.Elem() ifaceType = defaultMapType.Elem()
timeType = reflect.TypeOf(time.Time{})
ptrTimeType = reflect.TypeOf(&time.Time{})
) )
func newDecoder(strict bool) *decoder { func newDecoder(strict bool) *decoder {
d := &decoder{mapType: defaultMapType, strict: strict} d := &decoder{mapType: defaultMapType, strict: strict}
d.aliases = make(map[string]bool) d.aliases = make(map[*node]bool)
return d return d
} }
@ -251,7 +295,7 @@ func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
// //
// If n holds a null value, prepare returns before doing anything. // 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) { func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "" && n.implicit) { if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
return out, false, false return out, false, false
} }
again := true again := true
@ -274,7 +318,43 @@ func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unm
return out, false, false return out, false, false
} }
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) { 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")
}
switch n.kind { switch n.kind {
case documentNode: case documentNode:
return d.document(n, out) return d.document(n, out)
@ -308,16 +388,15 @@ func (d *decoder) document(n *node, out reflect.Value) (good bool) {
} }
func (d *decoder) alias(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 d.aliases[n] {
if !ok { // TODO this could actually be allowed in some circumstances.
failf("unknown anchor '%s' referenced", n.value)
}
if d.aliases[n.value] {
failf("anchor '%s' value contains itself", n.value) failf("anchor '%s' value contains itself", n.value)
} }
d.aliases[n.value] = true d.aliases[n] = true
good = d.unmarshal(an, out) d.aliasDepth++
delete(d.aliases, n.value) good = d.unmarshal(n.alias, out)
d.aliasDepth--
delete(d.aliases, n)
return good return good
} }
@ -329,7 +408,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 tag string
var resolved interface{} var resolved interface{}
if n.tag == "" && !n.implicit { if n.tag == "" && !n.implicit {
@ -353,9 +432,26 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
} }
return true return true
} }
if s, ok := resolved.(string); ok && out.CanAddr() { if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
if u, ok := out.Addr().Interface().(encoding.TextUnmarshaler); ok { // We've resolved to exactly the type we want, so use that.
err := u.UnmarshalText([]byte(s)) 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 { if err != nil {
fail(err) fail(err)
} }
@ -366,46 +462,54 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
case reflect.String: case reflect.String:
if tag == yaml_BINARY_TAG { if tag == yaml_BINARY_TAG {
out.SetString(resolved.(string)) out.SetString(resolved.(string))
good = true return true
} else if resolved != nil { }
if resolved != nil {
out.SetString(n.value) out.SetString(n.value)
good = true return true
} }
case reflect.Interface: case reflect.Interface:
if resolved == nil { if resolved == nil {
out.Set(reflect.Zero(out.Type())) 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 { } else {
out.Set(reflect.ValueOf(resolved)) out.Set(reflect.ValueOf(resolved))
} }
good = true return true
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
switch resolved := resolved.(type) { switch resolved := resolved.(type) {
case int: case int:
if !out.OverflowInt(int64(resolved)) { if !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved)) out.SetInt(int64(resolved))
good = true return true
} }
case int64: case int64:
if !out.OverflowInt(resolved) { if !out.OverflowInt(resolved) {
out.SetInt(resolved) out.SetInt(resolved)
good = true return true
} }
case uint64: case uint64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved)) out.SetInt(int64(resolved))
good = true return true
} }
case float64: case float64:
if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
out.SetInt(int64(resolved)) out.SetInt(int64(resolved))
good = true return true
} }
case string: case string:
if out.Type() == durationType { if out.Type() == durationType {
d, err := time.ParseDuration(resolved) d, err := time.ParseDuration(resolved)
if err == nil { if err == nil {
out.SetInt(int64(d)) out.SetInt(int64(d))
good = true return true
} }
} }
} }
@ -414,44 +518,49 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
case int: case int:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
case int64: case int64:
if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
case uint64: case uint64:
if !out.OverflowUint(uint64(resolved)) { if !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
case float64: case float64:
if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
out.SetUint(uint64(resolved)) out.SetUint(uint64(resolved))
good = true return true
} }
} }
case reflect.Bool: case reflect.Bool:
switch resolved := resolved.(type) { switch resolved := resolved.(type) {
case bool: case bool:
out.SetBool(resolved) out.SetBool(resolved)
good = true return true
} }
case reflect.Float32, reflect.Float64: case reflect.Float32, reflect.Float64:
switch resolved := resolved.(type) { switch resolved := resolved.(type) {
case int: case int:
out.SetFloat(float64(resolved)) out.SetFloat(float64(resolved))
good = true return true
case int64: case int64:
out.SetFloat(float64(resolved)) out.SetFloat(float64(resolved))
good = true return true
case uint64: case uint64:
out.SetFloat(float64(resolved)) out.SetFloat(float64(resolved))
good = true return true
case float64: case float64:
out.SetFloat(resolved) 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: case reflect.Ptr:
if out.Type().Elem() == reflect.TypeOf(resolved) { if out.Type().Elem() == reflect.TypeOf(resolved) {
@ -459,13 +568,11 @@ func (d *decoder) scalar(n *node, out reflect.Value) (good bool) {
elem := reflect.New(out.Type().Elem()) elem := reflect.New(out.Type().Elem())
elem.Elem().Set(reflect.ValueOf(resolved)) elem.Elem().Set(reflect.ValueOf(resolved))
out.Set(elem) out.Set(elem)
good = true return true
} }
} }
if !good {
d.terror(n, tag, out) d.terror(n, tag, out)
} return false
return good
} }
func settableValueOf(i interface{}) reflect.Value { func settableValueOf(i interface{}) reflect.Value {
@ -482,6 +589,10 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
switch out.Kind() { switch out.Kind() {
case reflect.Slice: case reflect.Slice:
out.Set(reflect.MakeSlice(out.Type(), l, l)) 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: case reflect.Interface:
// No type hints. Will have to use a generic sequence. // No type hints. Will have to use a generic sequence.
iface = out iface = out
@ -500,7 +611,9 @@ func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
j++ j++
} }
} }
if out.Kind() != reflect.Array {
out.Set(out.Slice(0, j)) out.Set(out.Slice(0, j))
}
if iface.IsValid() { if iface.IsValid() {
iface.Set(out) iface.Set(out)
} }
@ -561,7 +674,7 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
} }
e := reflect.New(et).Elem() e := reflect.New(et).Elem()
if d.unmarshal(n.children[i+1], e) { if d.unmarshal(n.children[i+1], e) {
out.SetMapIndex(k, e) d.setMapIndex(n.children[i+1], out, k, e)
} }
} }
} }
@ -569,6 +682,14 @@ func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
return true 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) { func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
outt := out.Type() outt := out.Type()
if outt.Elem() != mapItemType { if outt.Elem() != mapItemType {
@ -616,6 +737,10 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
elemType = inlineMap.Type().Elem() elemType = inlineMap.Type().Elem()
} }
var doneFields []bool
if d.strict {
doneFields = make([]bool, len(sinfo.FieldsList))
}
for i := 0; i < l; i += 2 { for i := 0; i < l; i += 2 {
ni := n.children[i] ni := n.children[i]
if isMerge(ni) { if isMerge(ni) {
@ -626,6 +751,13 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
continue continue
} }
if info, ok := sinfo.FieldsMap[name.String()]; ok { 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 var field reflect.Value
if info.Inline == nil { if info.Inline == nil {
field = out.Field(info.Num) field = out.Field(info.Num)
@ -639,9 +771,9 @@ func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
} }
value := reflect.New(elemType).Elem() value := reflect.New(elemType).Elem()
d.unmarshal(n.children[i+1], value) d.unmarshal(n.children[i+1], value)
inlineMap.SetMapIndex(name, value) d.setMapIndex(n.children[i+1], inlineMap, name, value)
} else if d.strict { } else if d.strict {
d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in struct %s", n.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 return true
@ -656,8 +788,7 @@ func (d *decoder) merge(n *node, out reflect.Value) {
case mappingNode: case mappingNode:
d.unmarshal(n, out) d.unmarshal(n, out)
case aliasNode: case aliasNode:
an, ok := d.doc.anchors[n.value] if n.alias != nil && n.alias.kind != mappingNode {
if ok && an.kind != mappingNode {
failWantMap() failWantMap()
} }
d.unmarshal(n, out) d.unmarshal(n, out)
@ -666,8 +797,7 @@ func (d *decoder) merge(n *node, out reflect.Value) {
for i := len(n.children) - 1; i >= 0; i-- { for i := len(n.children) - 1; i >= 0; i-- {
ni := n.children[i] ni := n.children[i]
if ni.kind == aliasNode { if ni.kind == aliasNode {
an, ok := d.doc.anchors[ni.value] if ni.alias != nil && ni.alias.kind != mappingNode {
if ok && an.kind != mappingNode {
failWantMap() failWantMap()
} }
} else if ni.kind != mappingNode { } else if ni.kind != mappingNode {

View file

@ -2,6 +2,7 @@ package yaml
import ( import (
"bytes" "bytes"
"fmt"
) )
// Flush the buffer if needed. // 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) return yaml_emitter_emit_mapping_start(emitter, event)
default: default:
return yaml_emitter_set_emitter_error(emitter, 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 return true
} }
// Write an achor. // Write an anchor.
func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool { func yaml_emitter_process_anchor(emitter *yaml_emitter_t) bool {
if emitter.anchor_data.anchor == nil { if emitter.anchor_data.anchor == nil {
return true return true

160
vendor/gopkg.in/yaml.v2/encode.go generated vendored
View file

@ -3,38 +3,67 @@ package yaml
import ( import (
"encoding" "encoding"
"fmt" "fmt"
"io"
"reflect" "reflect"
"regexp" "regexp"
"sort" "sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"unicode/utf8"
) )
// jsonNumber is the interface of the encoding/json.Number datatype.
// Repeating the interface here avoids a dependency on encoding/json, and also
// supports other libraries like jsoniter, which use a similar datatype with
// the same interface. Detecting this interface is useful when dealing with
// structures containing json.Number, which is a string under the hood. The
// encoder should prefer the use of Int64(), Float64() and string(), in that
// order, when encoding this type.
type jsonNumber interface {
Float64() (float64, error)
Int64() (int64, error)
String() string
}
type encoder struct { type encoder struct {
emitter yaml_emitter_t emitter yaml_emitter_t
event yaml_event_t event yaml_event_t
out []byte out []byte
flow bool flow bool
// doneInit holds whether the initial stream_start_event has been
// emitted.
doneInit bool
} }
func newEncoder() (e *encoder) { func newEncoder() *encoder {
e = &encoder{} e := &encoder{}
e.must(yaml_emitter_initialize(&e.emitter)) yaml_emitter_initialize(&e.emitter)
yaml_emitter_set_output_string(&e.emitter, &e.out) yaml_emitter_set_output_string(&e.emitter, &e.out)
yaml_emitter_set_unicode(&e.emitter, true) 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 return e
} }
func (e *encoder) finish() { func newEncoderWithWriter(w io.Writer) *encoder {
e.must(yaml_document_end_event_initialize(&e.event, true)) 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.emit()
e.doneInit = true
}
func (e *encoder) finish() {
e.emitter.open_ended = false e.emitter.open_ended = false
e.must(yaml_stream_end_event_initialize(&e.event)) yaml_stream_end_event_initialize(&e.event)
e.emit() e.emit()
} }
@ -44,9 +73,7 @@ func (e *encoder) destroy() {
func (e *encoder) emit() { func (e *encoder) emit() {
// This will internally delete the e.event value. // 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(yaml_emitter_emit(&e.emitter, &e.event))
e.must(false)
}
} }
func (e *encoder) must(ok bool) { func (e *encoder) must(ok bool) {
@ -59,13 +86,43 @@ 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) { func (e *encoder) marshal(tag string, in reflect.Value) {
if !in.IsValid() { if !in.IsValid() || in.Kind() == reflect.Ptr && in.IsNil() {
e.nilv() e.nilv()
return return
} }
iface := in.Interface() iface := in.Interface()
if m, ok := iface.(Marshaler); ok { switch m := iface.(type) {
case jsonNumber:
integer, err := m.Int64()
if err == nil {
// In this case the json.Number is a valid int64
in = reflect.ValueOf(integer)
break
}
float, err := m.Float64()
if err == nil {
// In this case the json.Number is a valid float64
in = reflect.ValueOf(float)
break
}
// fallback case - no number could be obtained
in = reflect.ValueOf(m.String())
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() v, err := m.MarshalYAML()
if err != nil { if err != nil {
fail(err) fail(err)
@ -75,31 +132,34 @@ func (e *encoder) marshal(tag string, in reflect.Value) {
return return
} }
in = reflect.ValueOf(v) in = reflect.ValueOf(v)
} else if m, ok := iface.(encoding.TextMarshaler); ok { case encoding.TextMarshaler:
text, err := m.MarshalText() text, err := m.MarshalText()
if err != nil { if err != nil {
fail(err) fail(err)
} }
in = reflect.ValueOf(string(text)) in = reflect.ValueOf(string(text))
case nil:
e.nilv()
return
} }
switch in.Kind() { switch in.Kind() {
case reflect.Interface: case reflect.Interface:
if in.IsNil() {
e.nilv()
} else {
e.marshal(tag, in.Elem()) e.marshal(tag, in.Elem())
}
case reflect.Map: case reflect.Map:
e.mapv(tag, in) e.mapv(tag, in)
case reflect.Ptr: case reflect.Ptr:
if in.IsNil() { if in.Type() == ptrTimeType {
e.nilv() e.timev(tag, in.Elem())
} else { } else {
e.marshal(tag, in.Elem()) e.marshal(tag, in.Elem())
} }
case reflect.Struct: case reflect.Struct:
if in.Type() == timeType {
e.timev(tag, in)
} else {
e.structv(tag, in) e.structv(tag, in)
case reflect.Slice: }
case reflect.Slice, reflect.Array:
if in.Type().Elem() == mapItemType { if in.Type().Elem() == mapItemType {
e.itemsv(tag, in) e.itemsv(tag, in)
} else { } else {
@ -191,10 +251,10 @@ func (e *encoder) mappingv(tag string, f func()) {
e.flow = false e.flow = false
style = yaml_FLOW_MAPPING_STYLE 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() e.emit()
f() f()
e.must(yaml_mapping_end_event_initialize(&e.event)) yaml_mapping_end_event_initialize(&e.event)
e.emit() e.emit()
} }
@ -240,23 +300,36 @@ var base60float = regexp.MustCompile(`^[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+(?:\.[0
func (e *encoder) stringv(tag string, in reflect.Value) { func (e *encoder) stringv(tag string, in reflect.Value) {
var style yaml_scalar_style_t var style yaml_scalar_style_t
s := in.String() s := in.String()
rtag, rs := resolve("", s) canUsePlain := true
if rtag == yaml_BINARY_TAG { switch {
if tag == "" || tag == yaml_STR_TAG { case !utf8.ValidString(s):
tag = rtag if tag == yaml_BINARY_TAG {
s = rs.(string)
} else if tag == yaml_BINARY_TAG {
failf("explicitly tagged !!binary data must be base64-encoded") failf("explicitly tagged !!binary data must be base64-encoded")
} else { }
if tag != "" {
failf("cannot marshal invalid UTF-8 data as %s", shortTag(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)) { // Note: it's possible for user code to emit invalid YAML
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE // if they explicitly specify a tag and a string containing
} else if strings.Contains(s, "\n") { // text that's incompatible with that tag.
switch {
case strings.Contains(s, "\n"):
style = yaml_LITERAL_SCALAR_STYLE style = yaml_LITERAL_SCALAR_STYLE
} else { case canUsePlain:
style = yaml_PLAIN_SCALAR_STYLE style = yaml_PLAIN_SCALAR_STYLE
default:
style = yaml_DOUBLE_QUOTED_SCALAR_STYLE
} }
e.emitScalar(s, "", tag, style) e.emitScalar(s, "", tag, style)
} }
@ -281,9 +354,20 @@ func (e *encoder) uintv(tag string, in reflect.Value) {
e.emitScalar(s, "", tag, yaml_PLAIN_SCALAR_STYLE) 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) { func (e *encoder) floatv(tag string, in reflect.Value) {
// FIXME: Handle 64 bits here. // Issue #352: When formatting, use the precision of the underlying value
s := strconv.FormatFloat(float64(in.Float()), 'g', -1, 32) precision := 64
if in.Kind() == reflect.Float32 {
precision = 32
}
s := strconv.FormatFloat(in.Float(), 'g', -1, precision)
switch s { switch s {
case "+Inf": case "+Inf":
s = ".inf" s = ".inf"

20
vendor/gopkg.in/yaml.v2/readerc.go generated vendored
View file

@ -93,9 +93,18 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
panic("read handler must be set") 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 the EOF flag is set and the raw buffer is empty, do nothing.
if parser.eof && parser.raw_buffer_pos == len(parser.raw_buffer) { 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. // Return if the buffer contains enough characters.
@ -389,6 +398,15 @@ func yaml_parser_update_buffer(parser *yaml_parser_t, length int) bool {
break 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] parser.buffer = parser.buffer[:buffer_len]
return true return true
} }

80
vendor/gopkg.in/yaml.v2/resolve.go generated vendored
View file

@ -6,7 +6,7 @@ import (
"regexp" "regexp"
"strconv" "strconv"
"strings" "strings"
"unicode/utf8" "time"
) )
type resolveMapItem struct { type resolveMapItem struct {
@ -75,13 +75,13 @@ func longTag(tag string) string {
func resolvableTag(tag string) bool { func resolvableTag(tag string) bool {
switch tag { 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 true
} }
return false return false
} }
var yamlStyleFloat = regexp.MustCompile(`^[-+]?[0-9]*\.?[0-9]+([eE][-+][0-9]+)?$`) var yamlStyleFloat = regexp.MustCompile(`^[-+]?(\.[0-9]+|[0-9]+(\.[0-9]*)?)([eE][-+]?[0-9]+)?$`)
func resolve(tag string, in string) (rtag string, out interface{}) { func resolve(tag string, in string) (rtag string, out interface{}) {
if !resolvableTag(tag) { if !resolvableTag(tag) {
@ -92,6 +92,19 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
switch tag { switch tag {
case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG: case "", rtag, yaml_STR_TAG, yaml_BINARY_TAG:
return 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)) 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': case 'D', 'S':
// Int, float, or timestamp. // 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) plain := strings.Replace(in, "_", "", -1)
intv, err := strconv.ParseInt(plain, 0, 64) intv, err := strconv.ParseInt(plain, 0, 64)
if err == nil { if err == nil {
@ -158,28 +180,20 @@ func resolve(tag string, in string) (rtag string, out interface{}) {
return yaml_INT_TAG, uintv return yaml_INT_TAG, uintv
} }
} else if strings.HasPrefix(plain, "-0b") { } 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 err == nil {
if intv == int64(int(intv)) { if true || intv == int64(int(intv)) {
return yaml_INT_TAG, -int(intv) return yaml_INT_TAG, int(intv)
} else { } else {
return yaml_INT_TAG, -intv return yaml_INT_TAG, intv
} }
} }
} }
// XXX Handle timestamps here.
default: default:
panic("resolveTable item not yet handled: " + string(rune(hint)) + " (with " + in + ")") 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_STR_TAG, in
}
return yaml_BINARY_TAG, encodeBase64(in)
} }
// encodeBase64 encodes s as base64 that is broken up into multiple lines // 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]) 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
}

134
vendor/gopkg.in/yaml.v2/scannerc.go generated vendored
View file

@ -626,31 +626,18 @@ func trace(args ...interface{}) func() {
func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool { func yaml_parser_fetch_more_tokens(parser *yaml_parser_t) bool {
// While we need more tokens to fetch, do it. // While we need more tokens to fetch, do it.
for { for {
// Check if we really need to fetch more tokens. if parser.tokens_head != len(parser.tokens) {
need_more_tokens := false // If queue is non-empty, check if any potential simple key may
// occupy the head position.
if parser.tokens_head == len(parser.tokens) { head_tok_idx, ok := parser.simple_keys_by_tok[parser.tokens_parsed]
// Queue is empty. if !ok {
need_more_tokens = true break
} else { } else if valid, ok := yaml_simple_key_is_valid(parser, &parser.simple_keys[head_tok_idx]); !ok {
// Check if any potential simple key may occupy the head position.
if !yaml_parser_stale_simple_keys(parser) {
return false return false
} } else if !valid {
for i := range parser.simple_keys {
simple_key := &parser.simple_keys[i]
if simple_key.possible && simple_key.token_number == parser.tokens_parsed {
need_more_tokens = true
break break
} }
} }
}
// We are finished.
if !need_more_tokens {
break
}
// Fetch the next token. // Fetch the next token.
if !yaml_parser_fetch_next_token(parser) { if !yaml_parser_fetch_next_token(parser) {
return false return false
@ -678,11 +665,6 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
return false return false
} }
// Remove obsolete potential simple keys.
if !yaml_parser_stale_simple_keys(parser) {
return false
}
// Check the indentation level against the current column. // Check the indentation level against the current column.
if !yaml_parser_unroll_indent(parser, parser.mark.column) { if !yaml_parser_unroll_indent(parser, parser.mark.column) {
return false return false
@ -837,29 +819,30 @@ func yaml_parser_fetch_next_token(parser *yaml_parser_t) bool {
"found character that cannot start any token") "found character that cannot start any token")
} }
// Check the list of potential simple keys and remove the positions that func yaml_simple_key_is_valid(parser *yaml_parser_t, simple_key *yaml_simple_key_t) (valid, ok bool) {
// cannot contain simple keys anymore. if !simple_key.possible {
func yaml_parser_stale_simple_keys(parser *yaml_parser_t) bool { return false, true
// Check for a potential simple key for each flow level. }
for i := range parser.simple_keys {
simple_key := &parser.simple_keys[i]
// The specification requires that a simple key // The 1.2 specification says:
// //
// - is limited to a single line, // "If the ? indicator is omitted, parsing needs to see past the
// - is shorter than 1024 characters. // implicit key to recognize it as such. To limit the amount of
if simple_key.possible && (simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index) { // lookahead required, the “:” indicator must appear at most 1024
// Unicode characters beyond the start of the key. In addition, the key
// is restricted to a single line."
//
if simple_key.mark.line < parser.mark.line || simple_key.mark.index+1024 < parser.mark.index {
// Check if the potential simple key to be removed is required. // Check if the potential simple key to be removed is required.
if simple_key.required { if simple_key.required {
return yaml_parser_set_scanner_error(parser, return false, yaml_parser_set_scanner_error(parser,
"while scanning a simple key", simple_key.mark, "while scanning a simple key", simple_key.mark,
"could not find expected ':'") "could not find expected ':'")
} }
simple_key.possible = false simple_key.possible = false
return false, true
} }
} return true, true
return true
} }
// Check if a simple key may start at the current position and add it if // Check if a simple key may start at the current position and add it if
@ -871,12 +854,6 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
required := parser.flow_level == 0 && parser.indent == parser.mark.column 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. // If the current position may start a simple key, save it.
// //
@ -885,13 +862,14 @@ func yaml_parser_save_simple_key(parser *yaml_parser_t) bool {
possible: true, possible: true,
required: required, required: required,
token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head), token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
mark: parser.mark,
} }
simple_key.mark = parser.mark
if !yaml_parser_remove_simple_key(parser) { if !yaml_parser_remove_simple_key(parser) {
return false return false
} }
parser.simple_keys[len(parser.simple_keys)-1] = simple_key parser.simple_keys[len(parser.simple_keys)-1] = simple_key
parser.simple_keys_by_tok[simple_key.token_number] = len(parser.simple_keys) - 1
} }
return true return true
} }
@ -906,19 +884,33 @@ func yaml_parser_remove_simple_key(parser *yaml_parser_t) bool {
"while scanning a simple key", parser.simple_keys[i].mark, "while scanning a simple key", parser.simple_keys[i].mark,
"could not find expected ':'") "could not find expected ':'")
} }
}
// Remove the key from the stack. // Remove the key from the stack.
parser.simple_keys[i].possible = false parser.simple_keys[i].possible = false
delete(parser.simple_keys_by_tok, parser.simple_keys[i].token_number)
}
return true return true
} }
// max_flow_level limits the flow_level
const max_flow_level = 10000
// Increase the flow level and resize the simple key list if needed. // Increase the flow level and resize the simple key list if needed.
func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool { func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
// Reset the simple key on the next level. // Reset the simple key on the next level.
parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{
possible: false,
required: false,
token_number: parser.tokens_parsed + (len(parser.tokens) - parser.tokens_head),
mark: parser.mark,
})
// Increase the flow level. // Increase the flow level.
parser.flow_level++ parser.flow_level++
if parser.flow_level > max_flow_level {
return yaml_parser_set_scanner_error(parser,
"while increasing flow level", parser.simple_keys[len(parser.simple_keys)-1].mark,
fmt.Sprintf("exceeded max depth of %d", max_flow_level))
}
return true return true
} }
@ -926,11 +918,16 @@ func yaml_parser_increase_flow_level(parser *yaml_parser_t) bool {
func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool { func yaml_parser_decrease_flow_level(parser *yaml_parser_t) bool {
if parser.flow_level > 0 { if parser.flow_level > 0 {
parser.flow_level-- parser.flow_level--
parser.simple_keys = parser.simple_keys[:len(parser.simple_keys)-1] last := len(parser.simple_keys) - 1
delete(parser.simple_keys_by_tok, parser.simple_keys[last].token_number)
parser.simple_keys = parser.simple_keys[:last]
} }
return true return true
} }
// max_indents limits the indents stack size
const max_indents = 10000
// Push the current indentation level to the stack and set the new level // Push the current indentation level to the stack and set the new level
// the current column is greater than the indentation level. In this case, // the current column is greater than the indentation level. In this case,
// append or insert the specified token into the token queue. // append or insert the specified token into the token queue.
@ -945,6 +942,11 @@ func yaml_parser_roll_indent(parser *yaml_parser_t, column, number int, typ yaml
// indentation level. // indentation level.
parser.indents = append(parser.indents, parser.indent) parser.indents = append(parser.indents, parser.indent)
parser.indent = column parser.indent = column
if len(parser.indents) > max_indents {
return yaml_parser_set_scanner_error(parser,
"while increasing indent level", parser.simple_keys[len(parser.simple_keys)-1].mark,
fmt.Sprintf("exceeded max depth of %d", max_indents))
}
// Create a token and insert it into the queue. // Create a token and insert it into the queue.
token := yaml_token_t{ token := yaml_token_t{
@ -995,6 +997,8 @@ func yaml_parser_fetch_stream_start(parser *yaml_parser_t) bool {
// Initialize the simple key stack. // Initialize the simple key stack.
parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{}) parser.simple_keys = append(parser.simple_keys, yaml_simple_key_t{})
parser.simple_keys_by_tok = make(map[int]int)
// A simple key is allowed at the beginning of the stream. // A simple key is allowed at the beginning of the stream.
parser.simple_key_allowed = true parser.simple_key_allowed = true
@ -1276,7 +1280,11 @@ func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
simple_key := &parser.simple_keys[len(parser.simple_keys)-1] simple_key := &parser.simple_keys[len(parser.simple_keys)-1]
// Have we found a simple key? // Have we found a simple key?
if simple_key.possible { if valid, ok := yaml_simple_key_is_valid(parser, simple_key); !ok {
return false
} else if valid {
// Create the KEY token and insert it into the queue. // Create the KEY token and insert it into the queue.
token := yaml_token_t{ token := yaml_token_t{
typ: yaml_KEY_TOKEN, typ: yaml_KEY_TOKEN,
@ -1294,6 +1302,7 @@ func yaml_parser_fetch_value(parser *yaml_parser_t) bool {
// Remove the simple key. // Remove the simple key.
simple_key.possible = false simple_key.possible = false
delete(parser.simple_keys_by_tok, simple_key.token_number)
// A simple key cannot follow another simple key. // A simple key cannot follow another simple key.
parser.simple_key_allowed = false parser.simple_key_allowed = false
@ -2475,6 +2484,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. // Check if we are at the end of the scalar.
if single { if single {
if parser.buffer[parser.buffer_pos] == '\'' { if parser.buffer[parser.buffer_pos] == '\'' {
@ -2487,10 +2500,6 @@ func yaml_parser_scan_flow_scalar(parser *yaml_parser_t, token *yaml_token_t, si
} }
// Consume blank characters. // 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) { for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
if is_blank(parser.buffer, parser.buffer_pos) { if is_blank(parser.buffer, parser.buffer_pos) {
// Consume a space or a tab character. // Consume a space or a tab character.
@ -2592,19 +2601,10 @@ func yaml_parser_scan_plain_scalar(parser *yaml_parser_t, token *yaml_token_t) b
// Consume non-blank characters. // Consume non-blank characters.
for !is_blankz(parser.buffer, parser.buffer_pos) { 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. // Check for indicators that may end a plain scalar.
if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) || if (parser.buffer[parser.buffer_pos] == ':' && is_blankz(parser.buffer, parser.buffer_pos+1)) ||
(parser.flow_level > 0 && (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] == ']' || 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 +2656,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) { for is_blank(parser.buffer, parser.buffer_pos) || is_break(parser.buffer, parser.buffer_pos) {
if is_blank(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) { 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", 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 return false
} }

9
vendor/gopkg.in/yaml.v2/sorter.go generated vendored
View file

@ -51,6 +51,15 @@ func (l keyList) Less(i, j int) bool {
} }
var ai, bi int var ai, bi int
var an, bn int64 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++ { for ai = i; ai < len(ar) && unicode.IsDigit(ar[ai]); ai++ {
an = an*10 + int64(ar[ai]-'0') an = an*10 + int64(ar[ai]-'0')
} }

63
vendor/gopkg.in/yaml.v2/writerc.go generated vendored
View file

@ -18,72 +18,9 @@ func yaml_emitter_flush(emitter *yaml_emitter_t) bool {
return true 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 { if err := emitter.write_handler(emitter, emitter.buffer[:emitter.buffer_pos]); err != nil {
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error()) return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
} }
emitter.buffer_pos = 0 emitter.buffer_pos = 0
return true 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 {
return yaml_emitter_set_writer_error(emitter, "write error: "+err.Error())
}
emitter.buffer_pos = 0
emitter.raw_buffer = emitter.raw_buffer[:0]
return true
} }

137
vendor/gopkg.in/yaml.v2/yaml.go generated vendored
View file

@ -9,6 +9,7 @@ package yaml
import ( import (
"errors" "errors"
"fmt" "fmt"
"io"
"reflect" "reflect"
"strings" "strings"
"sync" "sync"
@ -81,12 +82,58 @@ func Unmarshal(in []byte, out interface{}) (err error) {
} }
// UnmarshalStrict is like Unmarshal except that any fields that are found // 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. // an error.
func UnmarshalStrict(in []byte, out interface{}) (err error) { func UnmarshalStrict(in []byte, out interface{}) (err error) {
return unmarshal(in, out, true) return unmarshal(in, out, true)
} }
// A Decoder 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) { func unmarshal(in []byte, out interface{}, strict bool) (err error) {
defer handleErr(&err) defer handleErr(&err)
d := newDecoder(strict) 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. // 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. // 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 // Struct fields are only marshalled if they are exported (have an upper case
// first letter), and are unmarshalled using the field name lowercased as the // 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 // 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 // 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. // 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 // omitempty Only include the field if it's not set to the zero
// value for the type or to empty slices or maps. // 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 excluded if IsZero returns true.
// //
// flow Marshal using a flow style (useful for structs, // flow Marshal using a flow style (useful for structs,
// sequences and maps). // sequences and maps).
@ -140,7 +190,7 @@ func unmarshal(in []byte, out interface{}, strict bool) (err error) {
// For example: // For example:
// //
// type T struct { // type T struct {
// F int "a,omitempty" // F int `yaml:"a,omitempty"`
// B int // B int
// } // }
// yaml.Marshal(&T{B: 2}) // Returns "b: 2\n" // yaml.Marshal(&T{B: 2}) // Returns "b: 2\n"
@ -150,12 +200,47 @@ func Marshal(in interface{}) (out []byte, err error) {
defer handleErr(&err) defer handleErr(&err)
e := newEncoder() e := newEncoder()
defer e.destroy() defer e.destroy()
e.marshal("", reflect.ValueOf(in)) e.marshalDoc("", reflect.ValueOf(in))
e.finish() e.finish()
out = e.out out = e.out
return 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) { func handleErr(err *error) {
if v := recover(); v != nil { if v := recover(); v != nil {
if e, ok := v.(yamlError); ok { if e, ok := v.(yamlError); ok {
@ -211,6 +296,9 @@ type fieldInfo struct {
Num int Num int
OmitEmpty bool OmitEmpty bool
Flow 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 holds the field index if the field is part of an inlined struct.
Inline []int Inline []int
@ -290,6 +378,7 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
} else { } else {
finfo.Inline = append([]int{i}, finfo.Inline...) finfo.Inline = append([]int{i}, finfo.Inline...)
} }
finfo.Id = len(fieldsList)
fieldsMap[finfo.Key] = finfo fieldsMap[finfo.Key] = finfo
fieldsList = append(fieldsList, finfo) fieldsList = append(fieldsList, finfo)
} }
@ -311,11 +400,16 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
return nil, errors.New(msg) return nil, errors.New(msg)
} }
info.Id = len(fieldsList)
fieldsList = append(fieldsList, info) fieldsList = append(fieldsList, info)
fieldsMap[info.Key] = info fieldsMap[info.Key] = info
} }
sinfo = &structInfo{fieldsMap, fieldsList, inlineMap} sinfo = &structInfo{
FieldsMap: fieldsMap,
FieldsList: fieldsList,
InlineMap: inlineMap,
}
fieldMapMutex.Lock() fieldMapMutex.Lock()
structMap[st] = sinfo structMap[st] = sinfo
@ -323,8 +417,23 @@ func getStructInfo(st reflect.Type) (*structInfo, error) {
return sinfo, nil 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 { 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: case reflect.String:
return len(v.String()) == 0 return len(v.String()) == 0
case reflect.Interface, reflect.Ptr: case reflect.Interface, reflect.Ptr:
@ -355,3 +464,15 @@ func isZero(v reflect.Value) bool {
} }
return false return false
} }
// FutureLineWrap globally disables line wrapping when encoding long strings.
// This is a temporary and thus deprecated method introduced to faciliate
// migration towards v3, which offers more control of line lengths on
// individual encodings, and has a default matching the behavior introduced
// by this function.
//
// The default formatting of v2 was erroneously changed in v2.3.0 and reverted
// in v2.4.0, at which point this function was introduced to help migration.
func FutureLineWrap() {
disableLineWrapping = true
}

27
vendor/gopkg.in/yaml.v2/yamlh.go generated vendored
View file

@ -1,6 +1,7 @@
package yaml package yaml
import ( import (
"fmt"
"io" "io"
) )
@ -239,6 +240,27 @@ const (
yaml_MAPPING_END_EVENT // A MAPPING-END event. 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. // The event structure.
type yaml_event_t struct { type yaml_event_t struct {
@ -521,7 +543,7 @@ type yaml_parser_t struct {
read_handler yaml_read_handler_t // Read handler. read_handler yaml_read_handler_t // Read handler.
input_file io.Reader // File input data. input_reader io.Reader // File input data.
input []byte // String input data. input []byte // String input data.
input_pos int input_pos int
@ -557,6 +579,7 @@ type yaml_parser_t struct {
simple_key_allowed bool // May a simple key occur at the current position? simple_key_allowed bool // May a simple key occur at the current position?
simple_keys []yaml_simple_key_t // The stack of simple keys. simple_keys []yaml_simple_key_t // The stack of simple keys.
simple_keys_by_tok map[int]int // possible simple_key indexes indexed by token_number
// Parser stuff // Parser stuff
@ -632,7 +655,7 @@ type yaml_emitter_t struct {
write_handler yaml_write_handler_t // Write handler. write_handler yaml_write_handler_t // Write handler.
output_buffer *[]byte // String output data. 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 []byte // The working buffer.
buffer_pos int // The current position of the buffer. buffer_pos int // The current position of the buffer.

4
vendor/modules.txt vendored
View file

@ -30,6 +30,6 @@ golang.org/x/sys/unix
golang.org/x/sys/windows golang.org/x/sys/windows
# gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 # gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15
## explicit ## explicit
# gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7 # gopkg.in/yaml.v2 v2.4.0
## explicit ## explicit; go 1.15
gopkg.in/yaml.v2 gopkg.in/yaml.v2