gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

decode.go (20009B)


      1 package yaml
      2 
      3 import (
      4 	"encoding"
      5 	"encoding/base64"
      6 	"fmt"
      7 	"io"
      8 	"math"
      9 	"reflect"
     10 	"strconv"
     11 	"time"
     12 )
     13 
     14 const (
     15 	documentNode = 1 << iota
     16 	mappingNode
     17 	sequenceNode
     18 	scalarNode
     19 	aliasNode
     20 )
     21 
     22 type node struct {
     23 	kind         int
     24 	line, column int
     25 	tag          string
     26 	// For an alias node, alias holds the resolved alias.
     27 	alias    *node
     28 	value    string
     29 	implicit bool
     30 	children []*node
     31 	anchors  map[string]*node
     32 }
     33 
     34 // ----------------------------------------------------------------------------
     35 // Parser, produces a node tree out of a libyaml event stream.
     36 
     37 type parser struct {
     38 	parser   yaml_parser_t
     39 	event    yaml_event_t
     40 	doc      *node
     41 	doneInit bool
     42 }
     43 
     44 func newParser(b []byte) *parser {
     45 	p := parser{}
     46 	if !yaml_parser_initialize(&p.parser) {
     47 		panic("failed to initialize YAML emitter")
     48 	}
     49 	if len(b) == 0 {
     50 		b = []byte{'\n'}
     51 	}
     52 	yaml_parser_set_input_string(&p.parser, b)
     53 	return &p
     54 }
     55 
     56 func newParserFromReader(r io.Reader) *parser {
     57 	p := parser{}
     58 	if !yaml_parser_initialize(&p.parser) {
     59 		panic("failed to initialize YAML emitter")
     60 	}
     61 	yaml_parser_set_input_reader(&p.parser, r)
     62 	return &p
     63 }
     64 
     65 func (p *parser) init() {
     66 	if p.doneInit {
     67 		return
     68 	}
     69 	p.expect(yaml_STREAM_START_EVENT)
     70 	p.doneInit = true
     71 }
     72 
     73 func (p *parser) destroy() {
     74 	if p.event.typ != yaml_NO_EVENT {
     75 		yaml_event_delete(&p.event)
     76 	}
     77 	yaml_parser_delete(&p.parser)
     78 }
     79 
     80 // expect consumes an event from the event stream and
     81 // checks that it's of the expected type.
     82 func (p *parser) expect(e yaml_event_type_t) {
     83 	if p.event.typ == yaml_NO_EVENT {
     84 		if !yaml_parser_parse(&p.parser, &p.event) {
     85 			p.fail()
     86 		}
     87 	}
     88 	if p.event.typ == yaml_STREAM_END_EVENT {
     89 		failf("attempted to go past the end of stream; corrupted value?")
     90 	}
     91 	if p.event.typ != e {
     92 		p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ)
     93 		p.fail()
     94 	}
     95 	yaml_event_delete(&p.event)
     96 	p.event.typ = yaml_NO_EVENT
     97 }
     98 
     99 // peek peeks at the next event in the event stream,
    100 // puts the results into p.event and returns the event type.
    101 func (p *parser) peek() yaml_event_type_t {
    102 	if p.event.typ != yaml_NO_EVENT {
    103 		return p.event.typ
    104 	}
    105 	if !yaml_parser_parse(&p.parser, &p.event) {
    106 		p.fail()
    107 	}
    108 	return p.event.typ
    109 }
    110 
    111 func (p *parser) fail() {
    112 	var where string
    113 	var line int
    114 	if p.parser.problem_mark.line != 0 {
    115 		line = p.parser.problem_mark.line
    116 		// Scanner errors don't iterate line before returning error
    117 		if p.parser.error == yaml_SCANNER_ERROR {
    118 			line++
    119 		}
    120 	} else if p.parser.context_mark.line != 0 {
    121 		line = p.parser.context_mark.line
    122 	}
    123 	if line != 0 {
    124 		where = "line " + strconv.Itoa(line) + ": "
    125 	}
    126 	var msg string
    127 	if len(p.parser.problem) > 0 {
    128 		msg = p.parser.problem
    129 	} else {
    130 		msg = "unknown problem parsing YAML content"
    131 	}
    132 	failf("%s%s", where, msg)
    133 }
    134 
    135 func (p *parser) anchor(n *node, anchor []byte) {
    136 	if anchor != nil {
    137 		p.doc.anchors[string(anchor)] = n
    138 	}
    139 }
    140 
    141 func (p *parser) parse() *node {
    142 	p.init()
    143 	switch p.peek() {
    144 	case yaml_SCALAR_EVENT:
    145 		return p.scalar()
    146 	case yaml_ALIAS_EVENT:
    147 		return p.alias()
    148 	case yaml_MAPPING_START_EVENT:
    149 		return p.mapping()
    150 	case yaml_SEQUENCE_START_EVENT:
    151 		return p.sequence()
    152 	case yaml_DOCUMENT_START_EVENT:
    153 		return p.document()
    154 	case yaml_STREAM_END_EVENT:
    155 		// Happens when attempting to decode an empty buffer.
    156 		return nil
    157 	default:
    158 		panic("attempted to parse unknown event: " + p.event.typ.String())
    159 	}
    160 }
    161 
    162 func (p *parser) node(kind int) *node {
    163 	return &node{
    164 		kind:   kind,
    165 		line:   p.event.start_mark.line,
    166 		column: p.event.start_mark.column,
    167 	}
    168 }
    169 
    170 func (p *parser) document() *node {
    171 	n := p.node(documentNode)
    172 	n.anchors = make(map[string]*node)
    173 	p.doc = n
    174 	p.expect(yaml_DOCUMENT_START_EVENT)
    175 	n.children = append(n.children, p.parse())
    176 	p.expect(yaml_DOCUMENT_END_EVENT)
    177 	return n
    178 }
    179 
    180 func (p *parser) alias() *node {
    181 	n := p.node(aliasNode)
    182 	n.value = string(p.event.anchor)
    183 	n.alias = p.doc.anchors[n.value]
    184 	if n.alias == nil {
    185 		failf("unknown anchor '%s' referenced", n.value)
    186 	}
    187 	p.expect(yaml_ALIAS_EVENT)
    188 	return n
    189 }
    190 
    191 func (p *parser) scalar() *node {
    192 	n := p.node(scalarNode)
    193 	n.value = string(p.event.value)
    194 	n.tag = string(p.event.tag)
    195 	n.implicit = p.event.implicit
    196 	p.anchor(n, p.event.anchor)
    197 	p.expect(yaml_SCALAR_EVENT)
    198 	return n
    199 }
    200 
    201 func (p *parser) sequence() *node {
    202 	n := p.node(sequenceNode)
    203 	p.anchor(n, p.event.anchor)
    204 	p.expect(yaml_SEQUENCE_START_EVENT)
    205 	for p.peek() != yaml_SEQUENCE_END_EVENT {
    206 		n.children = append(n.children, p.parse())
    207 	}
    208 	p.expect(yaml_SEQUENCE_END_EVENT)
    209 	return n
    210 }
    211 
    212 func (p *parser) mapping() *node {
    213 	n := p.node(mappingNode)
    214 	p.anchor(n, p.event.anchor)
    215 	p.expect(yaml_MAPPING_START_EVENT)
    216 	for p.peek() != yaml_MAPPING_END_EVENT {
    217 		n.children = append(n.children, p.parse(), p.parse())
    218 	}
    219 	p.expect(yaml_MAPPING_END_EVENT)
    220 	return n
    221 }
    222 
    223 // ----------------------------------------------------------------------------
    224 // Decoder, unmarshals a node into a provided value.
    225 
    226 type decoder struct {
    227 	doc     *node
    228 	aliases map[*node]bool
    229 	mapType reflect.Type
    230 	terrors []string
    231 	strict  bool
    232 
    233 	decodeCount int
    234 	aliasCount  int
    235 	aliasDepth  int
    236 }
    237 
    238 var (
    239 	mapItemType    = reflect.TypeOf(MapItem{})
    240 	durationType   = reflect.TypeOf(time.Duration(0))
    241 	defaultMapType = reflect.TypeOf(map[interface{}]interface{}{})
    242 	ifaceType      = defaultMapType.Elem()
    243 	timeType       = reflect.TypeOf(time.Time{})
    244 	ptrTimeType    = reflect.TypeOf(&time.Time{})
    245 )
    246 
    247 func newDecoder(strict bool) *decoder {
    248 	d := &decoder{mapType: defaultMapType, strict: strict}
    249 	d.aliases = make(map[*node]bool)
    250 	return d
    251 }
    252 
    253 func (d *decoder) terror(n *node, tag string, out reflect.Value) {
    254 	if n.tag != "" {
    255 		tag = n.tag
    256 	}
    257 	value := n.value
    258 	if tag != yaml_SEQ_TAG && tag != yaml_MAP_TAG {
    259 		if len(value) > 10 {
    260 			value = " `" + value[:7] + "...`"
    261 		} else {
    262 			value = " `" + value + "`"
    263 		}
    264 	}
    265 	d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.line+1, shortTag(tag), value, out.Type()))
    266 }
    267 
    268 func (d *decoder) callUnmarshaler(n *node, u Unmarshaler) (good bool) {
    269 	terrlen := len(d.terrors)
    270 	err := u.UnmarshalYAML(func(v interface{}) (err error) {
    271 		defer handleErr(&err)
    272 		d.unmarshal(n, reflect.ValueOf(v))
    273 		if len(d.terrors) > terrlen {
    274 			issues := d.terrors[terrlen:]
    275 			d.terrors = d.terrors[:terrlen]
    276 			return &TypeError{issues}
    277 		}
    278 		return nil
    279 	})
    280 	if e, ok := err.(*TypeError); ok {
    281 		d.terrors = append(d.terrors, e.Errors...)
    282 		return false
    283 	}
    284 	if err != nil {
    285 		fail(err)
    286 	}
    287 	return true
    288 }
    289 
    290 // d.prepare initializes and dereferences pointers and calls UnmarshalYAML
    291 // if a value is found to implement it.
    292 // It returns the initialized and dereferenced out value, whether
    293 // unmarshalling was already done by UnmarshalYAML, and if so whether
    294 // its types unmarshalled appropriately.
    295 //
    296 // If n holds a null value, prepare returns before doing anything.
    297 func (d *decoder) prepare(n *node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) {
    298 	if n.tag == yaml_NULL_TAG || n.kind == scalarNode && n.tag == "" && (n.value == "null" || n.value == "~" || n.value == "" && n.implicit) {
    299 		return out, false, false
    300 	}
    301 	again := true
    302 	for again {
    303 		again = false
    304 		if out.Kind() == reflect.Ptr {
    305 			if out.IsNil() {
    306 				out.Set(reflect.New(out.Type().Elem()))
    307 			}
    308 			out = out.Elem()
    309 			again = true
    310 		}
    311 		if out.CanAddr() {
    312 			if u, ok := out.Addr().Interface().(Unmarshaler); ok {
    313 				good = d.callUnmarshaler(n, u)
    314 				return out, true, good
    315 			}
    316 		}
    317 	}
    318 	return out, false, false
    319 }
    320 
    321 const (
    322 	// 400,000 decode operations is ~500kb of dense object declarations, or
    323 	// ~5kb of dense object declarations with 10000% alias expansion
    324 	alias_ratio_range_low = 400000
    325 
    326 	// 4,000,000 decode operations is ~5MB of dense object declarations, or
    327 	// ~4.5MB of dense object declarations with 10% alias expansion
    328 	alias_ratio_range_high = 4000000
    329 
    330 	// alias_ratio_range is the range over which we scale allowed alias ratios
    331 	alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low)
    332 )
    333 
    334 func allowedAliasRatio(decodeCount int) float64 {
    335 	switch {
    336 	case decodeCount <= alias_ratio_range_low:
    337 		// allow 99% to come from alias expansion for small-to-medium documents
    338 		return 0.99
    339 	case decodeCount >= alias_ratio_range_high:
    340 		// allow 10% to come from alias expansion for very large documents
    341 		return 0.10
    342 	default:
    343 		// scale smoothly from 99% down to 10% over the range.
    344 		// this maps to 396,000 - 400,000 allowed alias-driven decodes over the range.
    345 		// 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps).
    346 		return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range)
    347 	}
    348 }
    349 
    350 func (d *decoder) unmarshal(n *node, out reflect.Value) (good bool) {
    351 	d.decodeCount++
    352 	if d.aliasDepth > 0 {
    353 		d.aliasCount++
    354 	}
    355 	if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) {
    356 		failf("document contains excessive aliasing")
    357 	}
    358 	switch n.kind {
    359 	case documentNode:
    360 		return d.document(n, out)
    361 	case aliasNode:
    362 		return d.alias(n, out)
    363 	}
    364 	out, unmarshaled, good := d.prepare(n, out)
    365 	if unmarshaled {
    366 		return good
    367 	}
    368 	switch n.kind {
    369 	case scalarNode:
    370 		good = d.scalar(n, out)
    371 	case mappingNode:
    372 		good = d.mapping(n, out)
    373 	case sequenceNode:
    374 		good = d.sequence(n, out)
    375 	default:
    376 		panic("internal error: unknown node kind: " + strconv.Itoa(n.kind))
    377 	}
    378 	return good
    379 }
    380 
    381 func (d *decoder) document(n *node, out reflect.Value) (good bool) {
    382 	if len(n.children) == 1 {
    383 		d.doc = n
    384 		d.unmarshal(n.children[0], out)
    385 		return true
    386 	}
    387 	return false
    388 }
    389 
    390 func (d *decoder) alias(n *node, out reflect.Value) (good bool) {
    391 	if d.aliases[n] {
    392 		// TODO this could actually be allowed in some circumstances.
    393 		failf("anchor '%s' value contains itself", n.value)
    394 	}
    395 	d.aliases[n] = true
    396 	d.aliasDepth++
    397 	good = d.unmarshal(n.alias, out)
    398 	d.aliasDepth--
    399 	delete(d.aliases, n)
    400 	return good
    401 }
    402 
    403 var zeroValue reflect.Value
    404 
    405 func resetMap(out reflect.Value) {
    406 	for _, k := range out.MapKeys() {
    407 		out.SetMapIndex(k, zeroValue)
    408 	}
    409 }
    410 
    411 func (d *decoder) scalar(n *node, out reflect.Value) bool {
    412 	var tag string
    413 	var resolved interface{}
    414 	if n.tag == "" && !n.implicit {
    415 		tag = yaml_STR_TAG
    416 		resolved = n.value
    417 	} else {
    418 		tag, resolved = resolve(n.tag, n.value)
    419 		if tag == yaml_BINARY_TAG {
    420 			data, err := base64.StdEncoding.DecodeString(resolved.(string))
    421 			if err != nil {
    422 				failf("!!binary value contains invalid base64 data")
    423 			}
    424 			resolved = string(data)
    425 		}
    426 	}
    427 	if resolved == nil {
    428 		if out.Kind() == reflect.Map && !out.CanAddr() {
    429 			resetMap(out)
    430 		} else {
    431 			out.Set(reflect.Zero(out.Type()))
    432 		}
    433 		return true
    434 	}
    435 	if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
    436 		// We've resolved to exactly the type we want, so use that.
    437 		out.Set(resolvedv)
    438 		return true
    439 	}
    440 	// Perhaps we can use the value as a TextUnmarshaler to
    441 	// set its value.
    442 	if out.CanAddr() {
    443 		u, ok := out.Addr().Interface().(encoding.TextUnmarshaler)
    444 		if ok {
    445 			var text []byte
    446 			if tag == yaml_BINARY_TAG {
    447 				text = []byte(resolved.(string))
    448 			} else {
    449 				// We let any value be unmarshaled into TextUnmarshaler.
    450 				// That might be more lax than we'd like, but the
    451 				// TextUnmarshaler itself should bowl out any dubious values.
    452 				text = []byte(n.value)
    453 			}
    454 			err := u.UnmarshalText(text)
    455 			if err != nil {
    456 				fail(err)
    457 			}
    458 			return true
    459 		}
    460 	}
    461 	switch out.Kind() {
    462 	case reflect.String:
    463 		if tag == yaml_BINARY_TAG {
    464 			out.SetString(resolved.(string))
    465 			return true
    466 		}
    467 		if resolved != nil {
    468 			out.SetString(n.value)
    469 			return true
    470 		}
    471 	case reflect.Interface:
    472 		if resolved == nil {
    473 			out.Set(reflect.Zero(out.Type()))
    474 		} else if tag == yaml_TIMESTAMP_TAG {
    475 			// It looks like a timestamp but for backward compatibility
    476 			// reasons we set it as a string, so that code that unmarshals
    477 			// timestamp-like values into interface{} will continue to
    478 			// see a string and not a time.Time.
    479 			// TODO(v3) Drop this.
    480 			out.Set(reflect.ValueOf(n.value))
    481 		} else {
    482 			out.Set(reflect.ValueOf(resolved))
    483 		}
    484 		return true
    485 	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    486 		switch resolved := resolved.(type) {
    487 		case int:
    488 			if !out.OverflowInt(int64(resolved)) {
    489 				out.SetInt(int64(resolved))
    490 				return true
    491 			}
    492 		case int64:
    493 			if !out.OverflowInt(resolved) {
    494 				out.SetInt(resolved)
    495 				return true
    496 			}
    497 		case uint64:
    498 			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
    499 				out.SetInt(int64(resolved))
    500 				return true
    501 			}
    502 		case float64:
    503 			if resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) {
    504 				out.SetInt(int64(resolved))
    505 				return true
    506 			}
    507 		case string:
    508 			if out.Type() == durationType {
    509 				d, err := time.ParseDuration(resolved)
    510 				if err == nil {
    511 					out.SetInt(int64(d))
    512 					return true
    513 				}
    514 			}
    515 		}
    516 	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
    517 		switch resolved := resolved.(type) {
    518 		case int:
    519 			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
    520 				out.SetUint(uint64(resolved))
    521 				return true
    522 			}
    523 		case int64:
    524 			if resolved >= 0 && !out.OverflowUint(uint64(resolved)) {
    525 				out.SetUint(uint64(resolved))
    526 				return true
    527 			}
    528 		case uint64:
    529 			if !out.OverflowUint(uint64(resolved)) {
    530 				out.SetUint(uint64(resolved))
    531 				return true
    532 			}
    533 		case float64:
    534 			if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) {
    535 				out.SetUint(uint64(resolved))
    536 				return true
    537 			}
    538 		}
    539 	case reflect.Bool:
    540 		switch resolved := resolved.(type) {
    541 		case bool:
    542 			out.SetBool(resolved)
    543 			return true
    544 		}
    545 	case reflect.Float32, reflect.Float64:
    546 		switch resolved := resolved.(type) {
    547 		case int:
    548 			out.SetFloat(float64(resolved))
    549 			return true
    550 		case int64:
    551 			out.SetFloat(float64(resolved))
    552 			return true
    553 		case uint64:
    554 			out.SetFloat(float64(resolved))
    555 			return true
    556 		case float64:
    557 			out.SetFloat(resolved)
    558 			return true
    559 		}
    560 	case reflect.Struct:
    561 		if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() {
    562 			out.Set(resolvedv)
    563 			return true
    564 		}
    565 	case reflect.Ptr:
    566 		if out.Type().Elem() == reflect.TypeOf(resolved) {
    567 			// TODO DOes this make sense? When is out a Ptr except when decoding a nil value?
    568 			elem := reflect.New(out.Type().Elem())
    569 			elem.Elem().Set(reflect.ValueOf(resolved))
    570 			out.Set(elem)
    571 			return true
    572 		}
    573 	}
    574 	d.terror(n, tag, out)
    575 	return false
    576 }
    577 
    578 func settableValueOf(i interface{}) reflect.Value {
    579 	v := reflect.ValueOf(i)
    580 	sv := reflect.New(v.Type()).Elem()
    581 	sv.Set(v)
    582 	return sv
    583 }
    584 
    585 func (d *decoder) sequence(n *node, out reflect.Value) (good bool) {
    586 	l := len(n.children)
    587 
    588 	var iface reflect.Value
    589 	switch out.Kind() {
    590 	case reflect.Slice:
    591 		out.Set(reflect.MakeSlice(out.Type(), l, l))
    592 	case reflect.Array:
    593 		if l != out.Len() {
    594 			failf("invalid array: want %d elements but got %d", out.Len(), l)
    595 		}
    596 	case reflect.Interface:
    597 		// No type hints. Will have to use a generic sequence.
    598 		iface = out
    599 		out = settableValueOf(make([]interface{}, l))
    600 	default:
    601 		d.terror(n, yaml_SEQ_TAG, out)
    602 		return false
    603 	}
    604 	et := out.Type().Elem()
    605 
    606 	j := 0
    607 	for i := 0; i < l; i++ {
    608 		e := reflect.New(et).Elem()
    609 		if ok := d.unmarshal(n.children[i], e); ok {
    610 			out.Index(j).Set(e)
    611 			j++
    612 		}
    613 	}
    614 	if out.Kind() != reflect.Array {
    615 		out.Set(out.Slice(0, j))
    616 	}
    617 	if iface.IsValid() {
    618 		iface.Set(out)
    619 	}
    620 	return true
    621 }
    622 
    623 func (d *decoder) mapping(n *node, out reflect.Value) (good bool) {
    624 	switch out.Kind() {
    625 	case reflect.Struct:
    626 		return d.mappingStruct(n, out)
    627 	case reflect.Slice:
    628 		return d.mappingSlice(n, out)
    629 	case reflect.Map:
    630 		// okay
    631 	case reflect.Interface:
    632 		if d.mapType.Kind() == reflect.Map {
    633 			iface := out
    634 			out = reflect.MakeMap(d.mapType)
    635 			iface.Set(out)
    636 		} else {
    637 			slicev := reflect.New(d.mapType).Elem()
    638 			if !d.mappingSlice(n, slicev) {
    639 				return false
    640 			}
    641 			out.Set(slicev)
    642 			return true
    643 		}
    644 	default:
    645 		d.terror(n, yaml_MAP_TAG, out)
    646 		return false
    647 	}
    648 	outt := out.Type()
    649 	kt := outt.Key()
    650 	et := outt.Elem()
    651 
    652 	mapType := d.mapType
    653 	if outt.Key() == ifaceType && outt.Elem() == ifaceType {
    654 		d.mapType = outt
    655 	}
    656 
    657 	if out.IsNil() {
    658 		out.Set(reflect.MakeMap(outt))
    659 	}
    660 	l := len(n.children)
    661 	for i := 0; i < l; i += 2 {
    662 		if isMerge(n.children[i]) {
    663 			d.merge(n.children[i+1], out)
    664 			continue
    665 		}
    666 		k := reflect.New(kt).Elem()
    667 		if d.unmarshal(n.children[i], k) {
    668 			kkind := k.Kind()
    669 			if kkind == reflect.Interface {
    670 				kkind = k.Elem().Kind()
    671 			}
    672 			if kkind == reflect.Map || kkind == reflect.Slice {
    673 				failf("invalid map key: %#v", k.Interface())
    674 			}
    675 			e := reflect.New(et).Elem()
    676 			if d.unmarshal(n.children[i+1], e) {
    677 				d.setMapIndex(n.children[i+1], out, k, e)
    678 			}
    679 		}
    680 	}
    681 	d.mapType = mapType
    682 	return true
    683 }
    684 
    685 func (d *decoder) setMapIndex(n *node, out, k, v reflect.Value) {
    686 	if d.strict && out.MapIndex(k) != zeroValue {
    687 		d.terrors = append(d.terrors, fmt.Sprintf("line %d: key %#v already set in map", n.line+1, k.Interface()))
    688 		return
    689 	}
    690 	out.SetMapIndex(k, v)
    691 }
    692 
    693 func (d *decoder) mappingSlice(n *node, out reflect.Value) (good bool) {
    694 	outt := out.Type()
    695 	if outt.Elem() != mapItemType {
    696 		d.terror(n, yaml_MAP_TAG, out)
    697 		return false
    698 	}
    699 
    700 	mapType := d.mapType
    701 	d.mapType = outt
    702 
    703 	var slice []MapItem
    704 	var l = len(n.children)
    705 	for i := 0; i < l; i += 2 {
    706 		if isMerge(n.children[i]) {
    707 			d.merge(n.children[i+1], out)
    708 			continue
    709 		}
    710 		item := MapItem{}
    711 		k := reflect.ValueOf(&item.Key).Elem()
    712 		if d.unmarshal(n.children[i], k) {
    713 			v := reflect.ValueOf(&item.Value).Elem()
    714 			if d.unmarshal(n.children[i+1], v) {
    715 				slice = append(slice, item)
    716 			}
    717 		}
    718 	}
    719 	out.Set(reflect.ValueOf(slice))
    720 	d.mapType = mapType
    721 	return true
    722 }
    723 
    724 func (d *decoder) mappingStruct(n *node, out reflect.Value) (good bool) {
    725 	sinfo, err := getStructInfo(out.Type())
    726 	if err != nil {
    727 		panic(err)
    728 	}
    729 	name := settableValueOf("")
    730 	l := len(n.children)
    731 
    732 	var inlineMap reflect.Value
    733 	var elemType reflect.Type
    734 	if sinfo.InlineMap != -1 {
    735 		inlineMap = out.Field(sinfo.InlineMap)
    736 		inlineMap.Set(reflect.New(inlineMap.Type()).Elem())
    737 		elemType = inlineMap.Type().Elem()
    738 	}
    739 
    740 	var doneFields []bool
    741 	if d.strict {
    742 		doneFields = make([]bool, len(sinfo.FieldsList))
    743 	}
    744 	for i := 0; i < l; i += 2 {
    745 		ni := n.children[i]
    746 		if isMerge(ni) {
    747 			d.merge(n.children[i+1], out)
    748 			continue
    749 		}
    750 		if !d.unmarshal(ni, name) {
    751 			continue
    752 		}
    753 		if info, ok := sinfo.FieldsMap[name.String()]; ok {
    754 			if d.strict {
    755 				if doneFields[info.Id] {
    756 					d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.line+1, name.String(), out.Type()))
    757 					continue
    758 				}
    759 				doneFields[info.Id] = true
    760 			}
    761 			var field reflect.Value
    762 			if info.Inline == nil {
    763 				field = out.Field(info.Num)
    764 			} else {
    765 				field = out.FieldByIndex(info.Inline)
    766 			}
    767 			d.unmarshal(n.children[i+1], field)
    768 		} else if sinfo.InlineMap != -1 {
    769 			if inlineMap.IsNil() {
    770 				inlineMap.Set(reflect.MakeMap(inlineMap.Type()))
    771 			}
    772 			value := reflect.New(elemType).Elem()
    773 			d.unmarshal(n.children[i+1], value)
    774 			d.setMapIndex(n.children[i+1], inlineMap, name, value)
    775 		} else if d.strict {
    776 			d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.line+1, name.String(), out.Type()))
    777 		}
    778 	}
    779 	return true
    780 }
    781 
    782 func failWantMap() {
    783 	failf("map merge requires map or sequence of maps as the value")
    784 }
    785 
    786 func (d *decoder) merge(n *node, out reflect.Value) {
    787 	switch n.kind {
    788 	case mappingNode:
    789 		d.unmarshal(n, out)
    790 	case aliasNode:
    791 		if n.alias != nil && n.alias.kind != mappingNode {
    792 			failWantMap()
    793 		}
    794 		d.unmarshal(n, out)
    795 	case sequenceNode:
    796 		// Step backwards as earlier nodes take precedence.
    797 		for i := len(n.children) - 1; i >= 0; i-- {
    798 			ni := n.children[i]
    799 			if ni.kind == aliasNode {
    800 				if ni.alias != nil && ni.alias.kind != mappingNode {
    801 					failWantMap()
    802 				}
    803 			} else if ni.kind != mappingNode {
    804 				failWantMap()
    805 			}
    806 			d.unmarshal(ni, out)
    807 		}
    808 	default:
    809 		failWantMap()
    810 	}
    811 }
    812 
    813 func isMerge(n *node) bool {
    814 	return n.kind == scalarNode && n.value == "<<" && (n.implicit == true || n.tag == yaml_MERGE_TAG)
    815 }