Blame vendor/gopkg.in/yaml.v2/decode.go

Packit 63bb0d
package yaml
Packit 63bb0d
Packit 63bb0d
import (
Packit 63bb0d
	"encoding"
Packit 63bb0d
	"encoding/base64"
Packit 63bb0d
	"fmt"
Packit 63bb0d
	"io"
Packit 63bb0d
	"math"
Packit 63bb0d
	"reflect"
Packit 63bb0d
	"strconv"
Packit 63bb0d
	"time"
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
const (
Packit 63bb0d
	documentNode = 1 << iota
Packit 63bb0d
	mappingNode
Packit 63bb0d
	sequenceNode
Packit 63bb0d
	scalarNode
Packit 63bb0d
	aliasNode
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
type node struct {
Packit 63bb0d
	kind         int
Packit 63bb0d
	line, column int
Packit 63bb0d
	tag          string
Packit 63bb0d
	// For an alias node, alias holds the resolved alias.
Packit 63bb0d
	alias    *node
Packit 63bb0d
	value    string
Packit 63bb0d
	implicit bool
Packit 63bb0d
	children []*node
Packit 63bb0d
	anchors  map[string]*node
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ----------------------------------------------------------------------------
Packit 63bb0d
// Parser, produces a node tree out of a libyaml event stream.
Packit 63bb0d
Packit 63bb0d
type parser struct {
Packit 63bb0d
	parser   yaml_parser_t
Packit 63bb0d
	event    yaml_event_t
Packit 63bb0d
	doc      *node
Packit 63bb0d
	doneInit bool
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func newParser(b []byte) *parser {
Packit 63bb0d
	p := parser{}
Packit 63bb0d
	if !yaml_parser_initialize(&p.parser) {
Packit 63bb0d
		panic("failed to initialize YAML emitter")
Packit 63bb0d
	}
Packit 63bb0d
	if len(b) == 0 {
Packit 63bb0d
		b = []byte{'\n'}
Packit 63bb0d
	}
Packit 63bb0d
	yaml_parser_set_input_string(&p.parser, b)
Packit 63bb0d
	return &p
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func newParserFromReader(r io.Reader) *parser {
Packit 63bb0d
	p := parser{}
Packit 63bb0d
	if !yaml_parser_initialize(&p.parser) {
Packit 63bb0d
		panic("failed to initialize YAML emitter")
Packit 63bb0d
	}
Packit 63bb0d
	yaml_parser_set_input_reader(&p.parser, r)
Packit 63bb0d
	return &p
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) init() {
Packit 63bb0d
	if p.doneInit {
Packit 63bb0d
		return
Packit 63bb0d
	}
Packit 63bb0d
	p.expect(yaml_STREAM_START_EVENT)
Packit 63bb0d
	p.doneInit = true
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) destroy() {
Packit 63bb0d
	if p.event.typ != yaml_NO_EVENT {
Packit 63bb0d
		yaml_event_delete(&p.event)
Packit 63bb0d
	}
Packit 63bb0d
	yaml_parser_delete(&p.parser)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// expect consumes an event from the event stream and
Packit 63bb0d
// checks that it's of the expected type.
Packit 63bb0d
func (p *parser) expect(e yaml_event_type_t) {
Packit 63bb0d
	if p.event.typ == yaml_NO_EVENT {
Packit 63bb0d
		if !yaml_parser_parse(&p.parser, &p.event) {
Packit 63bb0d
			p.fail()
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	if p.event.typ == yaml_STREAM_END_EVENT {
Packit 63bb0d
		failf("attempted to go past the end of stream; corrupted value?")
Packit 63bb0d
	}
Packit 63bb0d
	if p.event.typ != e {
Packit 63bb0d
		p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
Packit 63bb0d
		p.fail()
Packit 63bb0d
	}
Packit 63bb0d
	yaml_event_delete(&p.event)
Packit 63bb0d
	p.event.typ = yaml_NO_EVENT
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// peek peeks at the next event in the event stream,
Packit 63bb0d
// puts the results into p.event and returns the event type.
Packit 63bb0d
func (p *parser) peek() yaml_event_type_t {
Packit 63bb0d
	if p.event.typ != yaml_NO_EVENT {
Packit 63bb0d
		return p.event.typ
Packit 63bb0d
	}
Packit 63bb0d
	if !yaml_parser_parse(&p.parser, &p.event) {
Packit 63bb0d
		p.fail()
Packit 63bb0d
	}
Packit 63bb0d
	return p.event.typ
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) fail() {
Packit 63bb0d
	var where string
Packit 63bb0d
	var line int
Packit 63bb0d
	if p.parser.problem_mark.line != 0 {
Packit 63bb0d
		line = p.parser.problem_mark.line
Packit 63bb0d
		// Scanner errors don't iterate line before returning error
Packit 63bb0d
		if p.parser.error == yaml_SCANNER_ERROR {
Packit 63bb0d
			line++
Packit 63bb0d
		}
Packit 63bb0d
	} else if p.parser.context_mark.line != 0 {
Packit 63bb0d
		line = p.parser.context_mark.line
Packit 63bb0d
	}
Packit 63bb0d
	if line != 0 {
Packit 63bb0d
		where = "line " + strconv.Itoa(line) + ": "
Packit 63bb0d
	}
Packit 63bb0d
	var msg string
Packit 63bb0d
	if len(p.parser.problem) > 0 {
Packit 63bb0d
		msg = p.parser.problem
Packit 63bb0d
	} else {
Packit 63bb0d
		msg = "unknown problem parsing YAML content"
Packit 63bb0d
	}
Packit 63bb0d
	failf("%s%s", where, msg)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) anchor(n *node, anchor []byte) {
Packit 63bb0d
	if anchor != nil {
Packit 63bb0d
		p.doc.anchors[string(anchor)] = n
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) parse() *node {
Packit 63bb0d
	p.init()
Packit 63bb0d
	switch p.peek() {
Packit 63bb0d
	case yaml_SCALAR_EVENT:
Packit 63bb0d
		return p.scalar()
Packit 63bb0d
	case yaml_ALIAS_EVENT:
Packit 63bb0d
		return p.alias()
Packit 63bb0d
	case yaml_MAPPING_START_EVENT:
Packit 63bb0d
		return p.mapping()
Packit 63bb0d
	case yaml_SEQUENCE_START_EVENT:
Packit 63bb0d
		return p.sequence()
Packit 63bb0d
	case yaml_DOCUMENT_START_EVENT:
Packit 63bb0d
		return p.document()
Packit 63bb0d
	case yaml_STREAM_END_EVENT:
Packit 63bb0d
		// Happens when attempting to decode an empty buffer.
Packit 63bb0d
		return nil
Packit 63bb0d
	default:
Packit 63bb0d
		panic("attempted to parse unknown event: " + p.event.typ.String())
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) node(kind int) *node {
Packit 63bb0d
	return &node{
Packit 63bb0d
		kind:   kind,
Packit 63bb0d
		line:   p.event.start_mark.line,
Packit 63bb0d
		column: p.event.start_mark.column,
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) document() *node {
Packit 63bb0d
	n := p.node(documentNode)
Packit 63bb0d
	n.anchors = make(map[string]*node)
Packit 63bb0d
	p.doc = n
Packit 63bb0d
	p.expect(yaml_DOCUMENT_START_EVENT)
Packit 63bb0d
	n.children = append(n.children, p.parse())
Packit 63bb0d
	p.expect(yaml_DOCUMENT_END_EVENT)
Packit 63bb0d
	return n
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) alias() *node {
Packit 63bb0d
	n := p.node(aliasNode)
Packit 63bb0d
	n.value = string(p.event.anchor)
Packit 63bb0d
	n.alias = p.doc.anchors[n.value]
Packit 63bb0d
	if n.alias == nil {
Packit 63bb0d
		failf("unknown anchor '%s' referenced", n.value)
Packit 63bb0d
	}
Packit 63bb0d
	p.expect(yaml_ALIAS_EVENT)
Packit 63bb0d
	return n
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) scalar() *node {
Packit 63bb0d
	n := p.node(scalarNode)
Packit 63bb0d
	n.value = string(p.event.value)
Packit 63bb0d
	n.tag = string(p.event.tag)
Packit 63bb0d
	n.implicit = p.event.implicit
Packit 63bb0d
	p.anchor(n, p.event.anchor)
Packit 63bb0d
	p.expect(yaml_SCALAR_EVENT)
Packit 63bb0d
	return n
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) sequence() *node {
Packit 63bb0d
	n := p.node(sequenceNode)
Packit 63bb0d
	p.anchor(n, p.event.anchor)
Packit 63bb0d
	p.expect(yaml_SEQUENCE_START_EVENT)
Packit 63bb0d
	for p.peek() != yaml_SEQUENCE_END_EVENT {
Packit 63bb0d
		n.children = append(n.children, p.parse())
Packit 63bb0d
	}
Packit 63bb0d
	p.expect(yaml_SEQUENCE_END_EVENT)
Packit 63bb0d
	return n
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (p *parser) mapping() *node {
Packit 63bb0d
	n := p.node(mappingNode)
Packit 63bb0d
	p.anchor(n, p.event.anchor)
Packit 63bb0d
	p.expect(yaml_MAPPING_START_EVENT)
Packit 63bb0d
	for p.peek() != yaml_MAPPING_END_EVENT {
Packit 63bb0d
		n.children = append(n.children, p.parse(), p.parse())
Packit 63bb0d
	}
Packit 63bb0d
	p.expect(yaml_MAPPING_END_EVENT)
Packit 63bb0d
	return n
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// ----------------------------------------------------------------------------
Packit 63bb0d
// Decoder, unmarshals a node into a provided value.
Packit 63bb0d
Packit 63bb0d
type decoder struct {
Packit 63bb0d
	doc     *node
Packit 63bb0d
	aliases map[*node]bool
Packit 63bb0d
	mapType reflect.Type
Packit 63bb0d
	terrors []string
Packit 63bb0d
	strict  bool
Packit 63bb0d
Packit 63bb0d
	decodeCount int
Packit 63bb0d
	aliasCount  int
Packit 63bb0d
	aliasDepth  int
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
var (
Packit 63bb0d
	mapItemType    = reflect.TypeOf(MapItem{})
Packit 63bb0d
	durationType   = reflect.TypeOf(time.Duration(0))
Packit 63bb0d
	defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
Packit 63bb0d
	ifaceType      = defaultMapType.Elem()
Packit 63bb0d
	timeType       = reflect.TypeOf(time.Time{})
Packit 63bb0d
	ptrTimeType    = reflect.TypeOf(&time.Time{})
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
func newDecoder(strict bool) *decoder {
Packit 63bb0d
	d := &decoder{mapType: defaultMapType, strict: strict}
Packit 63bb0d
	d.aliases = make(map[*node]bool)
Packit 63bb0d
	return d
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) terror(n *node, tag string, out reflect.Value) {
Packit 63bb0d
	if n.tag != "" {
Packit 63bb0d
		tag = n.tag
Packit 63bb0d
	}
Packit 63bb0d
	value := n.value
Packit 63bb0d
	if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
Packit 63bb0d
		if len(value) > 10 {
Packit 63bb0d
			value = " `" + value[:7] + "...`"
Packit 63bb0d
		} else {
Packit 63bb0d
			value = " `" + value + "`"
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
Packit 63bb0d
	terrlen := len(d.terrors)
Packit 63bb0d
	err := u.UnmarshalYAML(func(v interface{}) (err error) {
Packit 63bb0d
		defer handleErr(&err)
Packit 63bb0d
		d.unmarshal(n, reflect.ValueOf(v))
Packit 63bb0d
		if len(d.terrors) > terrlen {
Packit 63bb0d
			issues := d.terrors[terrlen:]
Packit 63bb0d
			d.terrors = d.terrors[:terrlen]
Packit 63bb0d
			return &TypeError{issues}
Packit 63bb0d
		}
Packit 63bb0d
		return nil
Packit 63bb0d
	})
Packit 63bb0d
	if e, ok := err.(*TypeError); ok {
Packit 63bb0d
		d.terrors = append(d.terrors, e.Errors...)
Packit 63bb0d
		return false
Packit 63bb0d
	}
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		fail(err)
Packit 63bb0d
	}
Packit 63bb0d
	return true
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
// d.prepare initializes and dereferences pointers and calls UnmarshalYAML
Packit 63bb0d
// if a value is found to implement it.
Packit 63bb0d
// It returns the initialized and dereferenced out value, whether
Packit 63bb0d
// unmarshalling was already done by UnmarshalYAML, and if so whether
Packit 63bb0d
// its types unmarshalled appropriately.
Packit 63bb0d
//
Packit 63bb0d
// If n holds a null value, prepare returns before doing anything.
Packit 63bb0d
func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
Packit 63bb0d
	if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
Packit 63bb0d
		return out, false, false
Packit 63bb0d
	}
Packit 63bb0d
	again := true
Packit 63bb0d
	for again {
Packit 63bb0d
		again = false
Packit 63bb0d
		if out.Kind() == reflect.Ptr {
Packit 63bb0d
			if out.IsNil() {
Packit 63bb0d
				out.Set(reflect.New(out.Type().Elem()))
Packit 63bb0d
			}
Packit 63bb0d
			out = out.Elem()
Packit 63bb0d
			again = true
Packit 63bb0d
		}
Packit 63bb0d
		if out.CanAddr() {
Packit 63bb0d
			if u, ok := out.Addr().Interface().(Unmarshaler); ok {
Packit 63bb0d
				good = d.callUnmarshaler(n, u)
Packit 63bb0d
				return out, true, good
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	return out, false, false
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
const (
Packit 63bb0d
	// 400,000 decode operations is ~500kb of dense object declarations, or
Packit 63bb0d
	// ~5kb of dense object declarations with 10000% alias expansion
Packit 63bb0d
	alias_ratio_range_low = 400000
Packit 63bb0d
Packit 63bb0d
	// 4,000,000 decode operations is ~5MB of dense object declarations, or
Packit 63bb0d
	// ~4.5MB of dense object declarations with 10% alias expansion
Packit 63bb0d
	alias_ratio_range_high = 4000000
Packit 63bb0d
Packit 63bb0d
	// alias_ratio_range is the range over which we scale allowed alias ratios
Packit 63bb0d
	alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
Packit 63bb0d
)
Packit 63bb0d
Packit 63bb0d
func allowedAliasRatio(decodeCount int) float64 {
Packit 63bb0d
	switch {
Packit 63bb0d
	case decodeCount <= alias_ratio_range_low:
Packit 63bb0d
		// allow 99% to come from alias expansion for small-to-medium documents
Packit 63bb0d
		return 0.99
Packit 63bb0d
	case decodeCount >= alias_ratio_range_high:
Packit 63bb0d
		// allow 10% to come from alias expansion for very large documents
Packit 63bb0d
		return 0.10
Packit 63bb0d
	default:
Packit 63bb0d
		// scale smoothly from 99% down to 10% over the range.
Packit 63bb0d
		// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
Packit 63bb0d
		// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
Packit 63bb0d
		return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
Packit 63bb0d
	d.decodeCount++
Packit 63bb0d
	if d.aliasDepth > 0 {
Packit 63bb0d
		d.aliasCount++
Packit 63bb0d
	}
Packit 63bb0d
	if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
Packit 63bb0d
		failf("document contains excessive aliasing")
Packit 63bb0d
	}
Packit 63bb0d
	switch n.kind {
Packit 63bb0d
	case documentNode:
Packit 63bb0d
		return d.document(n, out)
Packit 63bb0d
	case aliasNode:
Packit 63bb0d
		return d.alias(n, out)
Packit 63bb0d
	}
Packit 63bb0d
	out, unmarshaled, good := d.prepare(n, out)
Packit 63bb0d
	if unmarshaled {
Packit 63bb0d
		return good
Packit 63bb0d
	}
Packit 63bb0d
	switch n.kind {
Packit 63bb0d
	case scalarNode:
Packit 63bb0d
		good = d.scalar(n, out)
Packit 63bb0d
	case mappingNode:
Packit 63bb0d
		good = d.mapping(n, out)
Packit 63bb0d
	case sequenceNode:
Packit 63bb0d
		good = d.sequence(n, out)
Packit 63bb0d
	default:
Packit 63bb0d
		panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
Packit 63bb0d
	}
Packit 63bb0d
	return good
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) document(n *node, out reflect.Value) (good bool) {
Packit 63bb0d
	if len(n.children) == 1 {
Packit 63bb0d
		d.doc = n
Packit 63bb0d
		d.unmarshal(n.children[0], out)
Packit 63bb0d
		return true
Packit 63bb0d
	}
Packit 63bb0d
	return false
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
Packit 63bb0d
	if d.aliases[n] {
Packit 63bb0d
		// TODO this could actually be allowed in some circumstances.
Packit 63bb0d
		failf("anchor '%s' value contains itself", n.value)
Packit 63bb0d
	}
Packit 63bb0d
	d.aliases[n] = true
Packit 63bb0d
	d.aliasDepth++
Packit 63bb0d
	good = d.unmarshal(n.alias, out)
Packit 63bb0d
	d.aliasDepth--
Packit 63bb0d
	delete(d.aliases, n)
Packit 63bb0d
	return good
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
var zeroValue reflect.Value
Packit 63bb0d
Packit 63bb0d
func resetMap(out reflect.Value) {
Packit 63bb0d
	for _, k := range out.MapKeys() {
Packit 63bb0d
		out.SetMapIndex(k, zeroValue)
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) scalar(n *node, out reflect.Value) bool {
Packit 63bb0d
	var tag string
Packit 63bb0d
	var resolved interface{}
Packit 63bb0d
	if n.tag == "" && !n.implicit {
Packit 63bb0d
		tag = yaml_STR_TAG
Packit 63bb0d
		resolved = n.value
Packit 63bb0d
	} else {
Packit 63bb0d
		tag, resolved = resolve(n.tag, n.value)
Packit 63bb0d
		if tag == yaml_BINARY_TAG {
Packit 63bb0d
			data, err := base64.StdEncoding.DecodeString(resolved.(string))
Packit 63bb0d
			if err != nil {
Packit 63bb0d
				failf("!!binary value contains invalid base64 data")
Packit 63bb0d
			}
Packit 63bb0d
			resolved = string(data)
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	if resolved == nil {
Packit 63bb0d
		if out.Kind() == reflect.Map && !out.CanAddr() {
Packit 63bb0d
			resetMap(out)
Packit 63bb0d
		} else {
Packit 63bb0d
			out.Set(reflect.Zero(out.Type()))
Packit 63bb0d
		}
Packit 63bb0d
		return true
Packit 63bb0d
	}
Packit 63bb0d
	if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
Packit 63bb0d
		// We've resolved to exactly the type we want, so use that.
Packit 63bb0d
		out.Set(resolvedv)
Packit 63bb0d
		return true
Packit 63bb0d
	}
Packit 63bb0d
	// Perhaps we can use the value as a TextUnmarshaler to
Packit 63bb0d
	// set its value.
Packit 63bb0d
	if out.CanAddr() {
Packit 63bb0d
		u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
Packit 63bb0d
		if ok {
Packit 63bb0d
			var text []byte
Packit 63bb0d
			if tag == yaml_BINARY_TAG {
Packit 63bb0d
				text = []byte(resolved.(string))
Packit 63bb0d
			} else {
Packit 63bb0d
				// We let any value be unmarshaled into TextUnmarshaler.
Packit 63bb0d
				// That might be more lax than we'd like, but the
Packit 63bb0d
				// TextUnmarshaler itself should bowl out any dubious values.
Packit 63bb0d
				text = []byte(n.value)
Packit 63bb0d
			}
Packit 63bb0d
			err := u.UnmarshalText(text)
Packit 63bb0d
			if err != nil {
Packit 63bb0d
				fail(err)
Packit 63bb0d
			}
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	switch out.Kind() {
Packit 63bb0d
	case reflect.String:
Packit 63bb0d
		if tag == yaml_BINARY_TAG {
Packit 63bb0d
			out.SetString(resolved.(string))
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
		if resolved != nil {
Packit 63bb0d
			out.SetString(n.value)
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
	case reflect.Interface:
Packit 63bb0d
		if resolved == nil {
Packit 63bb0d
			out.Set(reflect.Zero(out.Type()))
Packit 63bb0d
		} else if tag == yaml_TIMESTAMP_TAG {
Packit 63bb0d
			// It looks like a timestamp but for backward compatibility
Packit 63bb0d
			// reasons we set it as a string, so that code that unmarshals
Packit 63bb0d
			// timestamp-like values into interface{} will continue to
Packit 63bb0d
			// see a string and not a time.Time.
Packit 63bb0d
			// TODO(v3) Drop this.
Packit 63bb0d
			out.Set(reflect.ValueOf(n.value))
Packit 63bb0d
		} else {
Packit 63bb0d
			out.Set(reflect.ValueOf(resolved))
Packit 63bb0d
		}
Packit 63bb0d
		return true
Packit 63bb0d
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
Packit 63bb0d
		switch resolved := resolved.(type) {
Packit 63bb0d
		case int:
Packit 63bb0d
			if !out.OverflowInt(int64(resolved)) {
Packit 63bb0d
				out.SetInt(int64(resolved))
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		case int64:
Packit 63bb0d
			if !out.OverflowInt(resolved) {
Packit 63bb0d
				out.SetInt(resolved)
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		case uint64:
Packit 63bb0d
			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
Packit 63bb0d
				out.SetInt(int64(resolved))
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		case float64:
Packit 63bb0d
			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
Packit 63bb0d
				out.SetInt(int64(resolved))
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		case string:
Packit 63bb0d
			if out.Type() == durationType {
Packit 63bb0d
				d, err := time.ParseDuration(resolved)
Packit 63bb0d
				if err == nil {
Packit 63bb0d
					out.SetInt(int64(d))
Packit 63bb0d
					return true
Packit 63bb0d
				}
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
Packit 63bb0d
		switch resolved := resolved.(type) {
Packit 63bb0d
		case int:
Packit 63bb0d
			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
Packit 63bb0d
				out.SetUint(uint64(resolved))
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		case int64:
Packit 63bb0d
			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
Packit 63bb0d
				out.SetUint(uint64(resolved))
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		case uint64:
Packit 63bb0d
			if !out.OverflowUint(uint64(resolved)) {
Packit 63bb0d
				out.SetUint(uint64(resolved))
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		case float64:
Packit 63bb0d
			if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
Packit 63bb0d
				out.SetUint(uint64(resolved))
Packit 63bb0d
				return true
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
	case reflect.Bool:
Packit 63bb0d
		switch resolved := resolved.(type) {
Packit 63bb0d
		case bool:
Packit 63bb0d
			out.SetBool(resolved)
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
	case reflect.Float32, reflect.Float64:
Packit 63bb0d
		switch resolved := resolved.(type) {
Packit 63bb0d
		case int:
Packit 63bb0d
			out.SetFloat(float64(resolved))
Packit 63bb0d
			return true
Packit 63bb0d
		case int64:
Packit 63bb0d
			out.SetFloat(float64(resolved))
Packit 63bb0d
			return true
Packit 63bb0d
		case uint64:
Packit 63bb0d
			out.SetFloat(float64(resolved))
Packit 63bb0d
			return true
Packit 63bb0d
		case float64:
Packit 63bb0d
			out.SetFloat(resolved)
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
	case reflect.Struct:
Packit 63bb0d
		if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
Packit 63bb0d
			out.Set(resolvedv)
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
	case reflect.Ptr:
Packit 63bb0d
		if out.Type().Elem() == reflect.TypeOf(resolved) {
Packit 63bb0d
			// TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
Packit 63bb0d
			elem := reflect.New(out.Type().Elem())
Packit 63bb0d
			elem.Elem().Set(reflect.ValueOf(resolved))
Packit 63bb0d
			out.Set(elem)
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	d.terror(n, tag, out)
Packit 63bb0d
	return false
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func settableValueOf(i interface{}) reflect.Value {
Packit 63bb0d
	v := reflect.ValueOf(i)
Packit 63bb0d
	sv := reflect.New(v.Type()).Elem()
Packit 63bb0d
	sv.Set(v)
Packit 63bb0d
	return sv
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
Packit 63bb0d
	l := len(n.children)
Packit 63bb0d
Packit 63bb0d
	var iface reflect.Value
Packit 63bb0d
	switch out.Kind() {
Packit 63bb0d
	case reflect.Slice:
Packit 63bb0d
		out.Set(reflect.MakeSlice(out.Type(), l, l))
Packit 63bb0d
	case reflect.Array:
Packit 63bb0d
		if l != out.Len() {
Packit 63bb0d
			failf("invalid array: want %d elements but got %d", out.Len(), l)
Packit 63bb0d
		}
Packit 63bb0d
	case reflect.Interface:
Packit 63bb0d
		// No type hints. Will have to use a generic sequence.
Packit 63bb0d
		iface = out
Packit 63bb0d
		out = settableValueOf(make([]interface{}, l))
Packit 63bb0d
	default:
Packit 63bb0d
		d.terror(n, yaml_SEQ_TAG, out)
Packit 63bb0d
		return false
Packit 63bb0d
	}
Packit 63bb0d
	et := out.Type().Elem()
Packit 63bb0d
Packit 63bb0d
	j := 0
Packit 63bb0d
	for i := 0; i < l; i++ {
Packit 63bb0d
		e := reflect.New(et).Elem()
Packit 63bb0d
		if ok := d.unmarshal(n.children[i], e); ok {
Packit 63bb0d
			out.Index(j).Set(e)
Packit 63bb0d
			j++
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	if out.Kind() != reflect.Array {
Packit 63bb0d
		out.Set(out.Slice(0, j))
Packit 63bb0d
	}
Packit 63bb0d
	if iface.IsValid() {
Packit 63bb0d
		iface.Set(out)
Packit 63bb0d
	}
Packit 63bb0d
	return true
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
Packit 63bb0d
	switch out.Kind() {
Packit 63bb0d
	case reflect.Struct:
Packit 63bb0d
		return d.mappingStruct(n, out)
Packit 63bb0d
	case reflect.Slice:
Packit 63bb0d
		return d.mappingSlice(n, out)
Packit 63bb0d
	case reflect.Map:
Packit 63bb0d
		// okay
Packit 63bb0d
	case reflect.Interface:
Packit 63bb0d
		if d.mapType.Kind() == reflect.Map {
Packit 63bb0d
			iface := out
Packit 63bb0d
			out = reflect.MakeMap(d.mapType)
Packit 63bb0d
			iface.Set(out)
Packit 63bb0d
		} else {
Packit 63bb0d
			slicev := reflect.New(d.mapType).Elem()
Packit 63bb0d
			if !d.mappingSlice(n, slicev) {
Packit 63bb0d
				return false
Packit 63bb0d
			}
Packit 63bb0d
			out.Set(slicev)
Packit 63bb0d
			return true
Packit 63bb0d
		}
Packit 63bb0d
	default:
Packit 63bb0d
		d.terror(n, yaml_MAP_TAG, out)
Packit 63bb0d
		return false
Packit 63bb0d
	}
Packit 63bb0d
	outt := out.Type()
Packit 63bb0d
	kt := outt.Key()
Packit 63bb0d
	et := outt.Elem()
Packit 63bb0d
Packit 63bb0d
	mapType := d.mapType
Packit 63bb0d
	if outt.Key() == ifaceType && outt.Elem() == ifaceType {
Packit 63bb0d
		d.mapType = outt
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	if out.IsNil() {
Packit 63bb0d
		out.Set(reflect.MakeMap(outt))
Packit 63bb0d
	}
Packit 63bb0d
	l := len(n.children)
Packit 63bb0d
	for i := 0; i < l; i += 2 {
Packit 63bb0d
		if isMerge(n.children[i]) {
Packit 63bb0d
			d.merge(n.children[i+1], out)
Packit 63bb0d
			continue
Packit 63bb0d
		}
Packit 63bb0d
		k := reflect.New(kt).Elem()
Packit 63bb0d
		if d.unmarshal(n.children[i], k) {
Packit 63bb0d
			kkind := k.Kind()
Packit 63bb0d
			if kkind == reflect.Interface {
Packit 63bb0d
				kkind = k.Elem().Kind()
Packit 63bb0d
			}
Packit 63bb0d
			if kkind == reflect.Map || kkind == reflect.Slice {
Packit 63bb0d
				failf("invalid map key: %#v", k.Interface())
Packit 63bb0d
			}
Packit 63bb0d
			e := reflect.New(et).Elem()
Packit 63bb0d
			if d.unmarshal(n.children[i+1], e) {
Packit 63bb0d
				d.setMapIndex(n.children[i+1], out, k, e)
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	d.mapType = mapType
Packit 63bb0d
	return true
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
Packit 63bb0d
	if d.strict && out.MapIndex(k) != zeroValue {
Packit 63bb0d
		d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
Packit 63bb0d
		return
Packit 63bb0d
	}
Packit 63bb0d
	out.SetMapIndex(k, v)
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
Packit 63bb0d
	outt := out.Type()
Packit 63bb0d
	if outt.Elem() != mapItemType {
Packit 63bb0d
		d.terror(n, yaml_MAP_TAG, out)
Packit 63bb0d
		return false
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	mapType := d.mapType
Packit 63bb0d
	d.mapType = outt
Packit 63bb0d
Packit 63bb0d
	var slice []MapItem
Packit 63bb0d
	var l = len(n.children)
Packit 63bb0d
	for i := 0; i < l; i += 2 {
Packit 63bb0d
		if isMerge(n.children[i]) {
Packit 63bb0d
			d.merge(n.children[i+1], out)
Packit 63bb0d
			continue
Packit 63bb0d
		}
Packit 63bb0d
		item := MapItem{}
Packit 63bb0d
		k := reflect.ValueOf(&item.Key).Elem()
Packit 63bb0d
		if d.unmarshal(n.children[i], k) {
Packit 63bb0d
			v := reflect.ValueOf(&item.Value).Elem()
Packit 63bb0d
			if d.unmarshal(n.children[i+1], v) {
Packit 63bb0d
				slice = append(slice, item)
Packit 63bb0d
			}
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	out.Set(reflect.ValueOf(slice))
Packit 63bb0d
	d.mapType = mapType
Packit 63bb0d
	return true
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
Packit 63bb0d
	sinfo, err := getStructInfo(out.Type())
Packit 63bb0d
	if err != nil {
Packit 63bb0d
		panic(err)
Packit 63bb0d
	}
Packit 63bb0d
	name := settableValueOf("")
Packit 63bb0d
	l := len(n.children)
Packit 63bb0d
Packit 63bb0d
	var inlineMap reflect.Value
Packit 63bb0d
	var elemType reflect.Type
Packit 63bb0d
	if sinfo.InlineMap != -1 {
Packit 63bb0d
		inlineMap = out.Field(sinfo.InlineMap)
Packit 63bb0d
		inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
Packit 63bb0d
		elemType = inlineMap.Type().Elem()
Packit 63bb0d
	}
Packit 63bb0d
Packit 63bb0d
	var doneFields []bool
Packit 63bb0d
	if d.strict {
Packit 63bb0d
		doneFields = make([]bool, len(sinfo.FieldsList))
Packit 63bb0d
	}
Packit 63bb0d
	for i := 0; i < l; i += 2 {
Packit 63bb0d
		ni := n.children[i]
Packit 63bb0d
		if isMerge(ni) {
Packit 63bb0d
			d.merge(n.children[i+1], out)
Packit 63bb0d
			continue
Packit 63bb0d
		}
Packit 63bb0d
		if !d.unmarshal(ni, name) {
Packit 63bb0d
			continue
Packit 63bb0d
		}
Packit 63bb0d
		if info, ok := sinfo.FieldsMap[name.String()]; ok {
Packit 63bb0d
			if d.strict {
Packit 63bb0d
				if doneFields[info.Id] {
Packit 63bb0d
					d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
Packit 63bb0d
					continue
Packit 63bb0d
				}
Packit 63bb0d
				doneFields[info.Id] = true
Packit 63bb0d
			}
Packit 63bb0d
			var field reflect.Value
Packit 63bb0d
			if info.Inline == nil {
Packit 63bb0d
				field = out.Field(info.Num)
Packit 63bb0d
			} else {
Packit 63bb0d
				field = out.FieldByIndex(info.Inline)
Packit 63bb0d
			}
Packit 63bb0d
			d.unmarshal(n.children[i+1], field)
Packit 63bb0d
		} else if sinfo.InlineMap != -1 {
Packit 63bb0d
			if inlineMap.IsNil() {
Packit 63bb0d
				inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
Packit 63bb0d
			}
Packit 63bb0d
			value := reflect.New(elemType).Elem()
Packit 63bb0d
			d.unmarshal(n.children[i+1], value)
Packit 63bb0d
			d.setMapIndex(n.children[i+1], inlineMap, name, value)
Packit 63bb0d
		} else if d.strict {
Packit 63bb0d
			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
Packit 63bb0d
		}
Packit 63bb0d
	}
Packit 63bb0d
	return true
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func failWantMap() {
Packit 63bb0d
	failf("map merge requires map or sequence of maps as the value")
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func (d *decoder) merge(n *node, out reflect.Value) {
Packit 63bb0d
	switch n.kind {
Packit 63bb0d
	case mappingNode:
Packit 63bb0d
		d.unmarshal(n, out)
Packit 63bb0d
	case aliasNode:
Packit 63bb0d
		if n.alias != nil && n.alias.kind != mappingNode {
Packit 63bb0d
			failWantMap()
Packit 63bb0d
		}
Packit 63bb0d
		d.unmarshal(n, out)
Packit 63bb0d
	case sequenceNode:
Packit 63bb0d
		// Step backwards as earlier nodes take precedence.
Packit 63bb0d
		for i := len(n.children) - 1; i >= 0; i-- {
Packit 63bb0d
			ni := n.children[i]
Packit 63bb0d
			if ni.kind == aliasNode {
Packit 63bb0d
				if ni.alias != nil && ni.alias.kind != mappingNode {
Packit 63bb0d
					failWantMap()
Packit 63bb0d
				}
Packit 63bb0d
			} else if ni.kind != mappingNode {
Packit 63bb0d
				failWantMap()
Packit 63bb0d
			}
Packit 63bb0d
			d.unmarshal(ni, out)
Packit 63bb0d
		}
Packit 63bb0d
	default:
Packit 63bb0d
		failWantMap()
Packit 63bb0d
	}
Packit 63bb0d
}
Packit 63bb0d
Packit 63bb0d
func isMerge(n *node) bool {
Packit 63bb0d
	return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
Packit 63bb0d
}