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 }