github.com/nibnait/go-learn@v0.0.0-20220227013611-dfa47ea6d2da/src/pkg/mod/gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b/decode.go (about) 1 // 2 // Copyright (c) 2011-2019 Canonical Ltd 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 package yaml 17 18 import ( 19 "encoding" 20 "encoding/base64" 21 "fmt" 22 "io" 23 "math" 24 "reflect" 25 "strconv" 26 "time" 27 ) 28 29 // ---------------------------------------------------------------------------- 30 // Parser, produces a node tree out of a libyaml event stream. 31 32 type parser struct { 33 parser yaml_parser_t 34 event yaml_event_t 35 doc *Node 36 anchors map[string]*Node 37 doneInit bool 38 textless bool 39 } 40 41 func newParser(b []byte) *parser { 42 p := parser{} 43 if !yaml_parser_initialize(&p.parser) { 44 panic("failed to initialize YAML emitter") 45 } 46 if len(b) == 0 { 47 b = []byte{'\n'} 48 } 49 yaml_parser_set_input_string(&p.parser, b) 50 return &p 51 } 52 53 func newParserFromReader(r io.Reader) *parser { 54 p := parser{} 55 if !yaml_parser_initialize(&p.parser) { 56 panic("failed to initialize YAML emitter") 57 } 58 yaml_parser_set_input_reader(&p.parser, r) 59 return &p 60 } 61 62 func (p *parser) init() { 63 if p.doneInit { 64 return 65 } 66 p.anchors = make(map[string]*Node) 67 p.expect(yaml_STREAM_START_EVENT) 68 p.doneInit = true 69 } 70 71 func (p *parser) destroy() { 72 if p.event.typ != yaml_NO_EVENT { 73 yaml_event_delete(&p.event) 74 } 75 yaml_parser_delete(&p.parser) 76 } 77 78 // expect consumes an event from the event stream and 79 // checks that it's of the expected type. 80 func (p *parser) expect(e yaml_event_type_t) { 81 if p.event.typ == yaml_NO_EVENT { 82 if !yaml_parser_parse(&p.parser, &p.event) { 83 p.fail() 84 } 85 } 86 if p.event.typ == yaml_STREAM_END_EVENT { 87 failf("attempted to go past the end of stream; corrupted value?") 88 } 89 if p.event.typ != e { 90 p.parser.problem = fmt.Sprintf("expected %s event but got %s", e, p.event.typ) 91 p.fail() 92 } 93 yaml_event_delete(&p.event) 94 p.event.typ = yaml_NO_EVENT 95 } 96 97 // peek peeks at the next event in the event stream, 98 // puts the results into p.event and returns the event type. 99 func (p *parser) peek() yaml_event_type_t { 100 if p.event.typ != yaml_NO_EVENT { 101 return p.event.typ 102 } 103 if !yaml_parser_parse(&p.parser, &p.event) { 104 p.fail() 105 } 106 return p.event.typ 107 } 108 109 func (p *parser) fail() { 110 var where string 111 var line int 112 if p.parser.context_mark.line != 0 { 113 line = p.parser.context_mark.line 114 // Scanner errors don't iterate line before returning error 115 if p.parser.error == yaml_SCANNER_ERROR { 116 line++ 117 } 118 } else if p.parser.problem_mark.line != 0 { 119 line = p.parser.problem_mark.line 120 // Scanner errors don't iterate line before returning error 121 if p.parser.error == yaml_SCANNER_ERROR { 122 line++ 123 } 124 } 125 if line != 0 { 126 where = "line " + strconv.Itoa(line) + ": " 127 } 128 var msg string 129 if len(p.parser.problem) > 0 { 130 msg = p.parser.problem 131 } else { 132 msg = "unknown problem parsing YAML content" 133 } 134 failf("%s%s", where, msg) 135 } 136 137 func (p *parser) anchor(n *Node, anchor []byte) { 138 if anchor != nil { 139 n.Anchor = string(anchor) 140 p.anchors[n.Anchor] = n 141 } 142 } 143 144 func (p *parser) parse() *Node { 145 p.init() 146 switch p.peek() { 147 case yaml_SCALAR_EVENT: 148 return p.scalar() 149 case yaml_ALIAS_EVENT: 150 return p.alias() 151 case yaml_MAPPING_START_EVENT: 152 return p.mapping() 153 case yaml_SEQUENCE_START_EVENT: 154 return p.sequence() 155 case yaml_DOCUMENT_START_EVENT: 156 return p.document() 157 case yaml_STREAM_END_EVENT: 158 // Happens when attempting to decode an empty buffer. 159 return nil 160 case yaml_TAIL_COMMENT_EVENT: 161 panic("internal error: unexpected tail comment event (please report)") 162 default: 163 panic("internal error: attempted to parse unknown event (please report): " + p.event.typ.String()) 164 } 165 } 166 167 func (p *parser) node(kind Kind, defaultTag, tag, value string) *Node { 168 var style Style 169 if tag != "" && tag != "!" { 170 tag = shortTag(tag) 171 style = TaggedStyle 172 } else if defaultTag != "" { 173 tag = defaultTag 174 } else if kind == ScalarNode { 175 tag, _ = resolve("", value) 176 } 177 n := &Node{ 178 Kind: kind, 179 Tag: tag, 180 Value: value, 181 Style: style, 182 } 183 if !p.textless { 184 n.Line = p.event.start_mark.line + 1 185 n.Column = p.event.start_mark.column + 1 186 n.HeadComment = string(p.event.head_comment) 187 n.LineComment = string(p.event.line_comment) 188 n.FootComment = string(p.event.foot_comment) 189 } 190 return n 191 } 192 193 func (p *parser) parseChild(parent *Node) *Node { 194 child := p.parse() 195 parent.Content = append(parent.Content, child) 196 return child 197 } 198 199 func (p *parser) document() *Node { 200 n := p.node(DocumentNode, "", "", "") 201 p.doc = n 202 p.expect(yaml_DOCUMENT_START_EVENT) 203 p.parseChild(n) 204 if p.peek() == yaml_DOCUMENT_END_EVENT { 205 n.FootComment = string(p.event.foot_comment) 206 } 207 p.expect(yaml_DOCUMENT_END_EVENT) 208 return n 209 } 210 211 func (p *parser) alias() *Node { 212 n := p.node(AliasNode, "", "", string(p.event.anchor)) 213 n.Alias = p.anchors[n.Value] 214 if n.Alias == nil { 215 failf("unknown anchor '%s' referenced", n.Value) 216 } 217 p.expect(yaml_ALIAS_EVENT) 218 return n 219 } 220 221 func (p *parser) scalar() *Node { 222 var parsedStyle = p.event.scalar_style() 223 var nodeStyle Style 224 switch { 225 case parsedStyle&yaml_DOUBLE_QUOTED_SCALAR_STYLE != 0: 226 nodeStyle = DoubleQuotedStyle 227 case parsedStyle&yaml_SINGLE_QUOTED_SCALAR_STYLE != 0: 228 nodeStyle = SingleQuotedStyle 229 case parsedStyle&yaml_LITERAL_SCALAR_STYLE != 0: 230 nodeStyle = LiteralStyle 231 case parsedStyle&yaml_FOLDED_SCALAR_STYLE != 0: 232 nodeStyle = FoldedStyle 233 } 234 var nodeValue = string(p.event.value) 235 var nodeTag = string(p.event.tag) 236 var defaultTag string 237 if nodeStyle == 0 { 238 if nodeValue == "<<" { 239 defaultTag = mergeTag 240 } 241 } else { 242 defaultTag = strTag 243 } 244 n := p.node(ScalarNode, defaultTag, nodeTag, nodeValue) 245 n.Style |= nodeStyle 246 p.anchor(n, p.event.anchor) 247 p.expect(yaml_SCALAR_EVENT) 248 return n 249 } 250 251 func (p *parser) sequence() *Node { 252 n := p.node(SequenceNode, seqTag, string(p.event.tag), "") 253 if p.event.sequence_style()&yaml_FLOW_SEQUENCE_STYLE != 0 { 254 n.Style |= FlowStyle 255 } 256 p.anchor(n, p.event.anchor) 257 p.expect(yaml_SEQUENCE_START_EVENT) 258 for p.peek() != yaml_SEQUENCE_END_EVENT { 259 p.parseChild(n) 260 } 261 n.LineComment = string(p.event.line_comment) 262 n.FootComment = string(p.event.foot_comment) 263 p.expect(yaml_SEQUENCE_END_EVENT) 264 return n 265 } 266 267 func (p *parser) mapping() *Node { 268 n := p.node(MappingNode, mapTag, string(p.event.tag), "") 269 block := true 270 if p.event.mapping_style()&yaml_FLOW_MAPPING_STYLE != 0 { 271 block = false 272 n.Style |= FlowStyle 273 } 274 p.anchor(n, p.event.anchor) 275 p.expect(yaml_MAPPING_START_EVENT) 276 for p.peek() != yaml_MAPPING_END_EVENT { 277 k := p.parseChild(n) 278 if block && k.FootComment != "" { 279 // Must be a foot comment for the prior value when being dedented. 280 if len(n.Content) > 2 { 281 n.Content[len(n.Content)-3].FootComment = k.FootComment 282 k.FootComment = "" 283 } 284 } 285 v := p.parseChild(n) 286 if k.FootComment == "" && v.FootComment != "" { 287 k.FootComment = v.FootComment 288 v.FootComment = "" 289 } 290 if p.peek() == yaml_TAIL_COMMENT_EVENT { 291 if k.FootComment == "" { 292 k.FootComment = string(p.event.foot_comment) 293 } 294 p.expect(yaml_TAIL_COMMENT_EVENT) 295 } 296 } 297 n.LineComment = string(p.event.line_comment) 298 n.FootComment = string(p.event.foot_comment) 299 if n.Style&FlowStyle == 0 && n.FootComment != "" && len(n.Content) > 1 { 300 n.Content[len(n.Content)-2].FootComment = n.FootComment 301 n.FootComment = "" 302 } 303 p.expect(yaml_MAPPING_END_EVENT) 304 return n 305 } 306 307 // ---------------------------------------------------------------------------- 308 // Decoder, unmarshals a node into a provided value. 309 310 type decoder struct { 311 doc *Node 312 aliases map[*Node]bool 313 terrors []string 314 315 stringMapType reflect.Type 316 generalMapType reflect.Type 317 318 knownFields bool 319 uniqueKeys bool 320 decodeCount int 321 aliasCount int 322 aliasDepth int 323 } 324 325 var ( 326 nodeType = reflect.TypeOf(Node{}) 327 durationType = reflect.TypeOf(time.Duration(0)) 328 stringMapType = reflect.TypeOf(map[string]interface{}{}) 329 generalMapType = reflect.TypeOf(map[interface{}]interface{}{}) 330 ifaceType = generalMapType.Elem() 331 timeType = reflect.TypeOf(time.Time{}) 332 ptrTimeType = reflect.TypeOf(&time.Time{}) 333 ) 334 335 func newDecoder() *decoder { 336 d := &decoder{ 337 stringMapType: stringMapType, 338 generalMapType: generalMapType, 339 uniqueKeys: true, 340 } 341 d.aliases = make(map[*Node]bool) 342 return d 343 } 344 345 func (d *decoder) terror(n *Node, tag string, out reflect.Value) { 346 if n.Tag != "" { 347 tag = n.Tag 348 } 349 value := n.Value 350 if tag != seqTag && tag != mapTag { 351 if len(value) > 10 { 352 value = " `" + value[:7] + "...`" 353 } else { 354 value = " `" + value + "`" 355 } 356 } 357 d.terrors = append(d.terrors, fmt.Sprintf("line %d: cannot unmarshal %s%s into %s", n.Line, shortTag(tag), value, out.Type())) 358 } 359 360 func (d *decoder) callUnmarshaler(n *Node, u Unmarshaler) (good bool) { 361 err := u.UnmarshalYAML(n) 362 if e, ok := err.(*TypeError); ok { 363 d.terrors = append(d.terrors, e.Errors...) 364 return false 365 } 366 if err != nil { 367 fail(err) 368 } 369 return true 370 } 371 372 func (d *decoder) callObsoleteUnmarshaler(n *Node, u obsoleteUnmarshaler) (good bool) { 373 terrlen := len(d.terrors) 374 err := u.UnmarshalYAML(func(v interface{}) (err error) { 375 defer handleErr(&err) 376 d.unmarshal(n, reflect.ValueOf(v)) 377 if len(d.terrors) > terrlen { 378 issues := d.terrors[terrlen:] 379 d.terrors = d.terrors[:terrlen] 380 return &TypeError{issues} 381 } 382 return nil 383 }) 384 if e, ok := err.(*TypeError); ok { 385 d.terrors = append(d.terrors, e.Errors...) 386 return false 387 } 388 if err != nil { 389 fail(err) 390 } 391 return true 392 } 393 394 // d.prepare initializes and dereferences pointers and calls UnmarshalYAML 395 // if a value is found to implement it. 396 // It returns the initialized and dereferenced out value, whether 397 // unmarshalling was already done by UnmarshalYAML, and if so whether 398 // its types unmarshalled appropriately. 399 // 400 // If n holds a null value, prepare returns before doing anything. 401 func (d *decoder) prepare(n *Node, out reflect.Value) (newout reflect.Value, unmarshaled, good bool) { 402 if n.ShortTag() == nullTag { 403 return out, false, false 404 } 405 again := true 406 for again { 407 again = false 408 if out.Kind() == reflect.Ptr { 409 if out.IsNil() { 410 out.Set(reflect.New(out.Type().Elem())) 411 } 412 out = out.Elem() 413 again = true 414 } 415 if out.CanAddr() { 416 outi := out.Addr().Interface() 417 if u, ok := outi.(Unmarshaler); ok { 418 good = d.callUnmarshaler(n, u) 419 return out, true, good 420 } 421 if u, ok := outi.(obsoleteUnmarshaler); ok { 422 good = d.callObsoleteUnmarshaler(n, u) 423 return out, true, good 424 } 425 } 426 } 427 return out, false, false 428 } 429 430 func (d *decoder) fieldByIndex(n *Node, v reflect.Value, index []int) (field reflect.Value) { 431 if n.ShortTag() == nullTag { 432 return reflect.Value{} 433 } 434 for _, num := range index { 435 for { 436 if v.Kind() == reflect.Ptr { 437 if v.IsNil() { 438 v.Set(reflect.New(v.Type().Elem())) 439 } 440 v = v.Elem() 441 continue 442 } 443 break 444 } 445 v = v.Field(num) 446 } 447 return v 448 } 449 450 const ( 451 // 400,000 decode operations is ~500kb of dense object declarations, or 452 // ~5kb of dense object declarations with 10000% alias expansion 453 alias_ratio_range_low = 400000 454 455 // 4,000,000 decode operations is ~5MB of dense object declarations, or 456 // ~4.5MB of dense object declarations with 10% alias expansion 457 alias_ratio_range_high = 4000000 458 459 // alias_ratio_range is the range over which we scale allowed alias ratios 460 alias_ratio_range = float64(alias_ratio_range_high - alias_ratio_range_low) 461 ) 462 463 func allowedAliasRatio(decodeCount int) float64 { 464 switch { 465 case decodeCount <= alias_ratio_range_low: 466 // allow 99% to come from alias expansion for small-to-medium documents 467 return 0.99 468 case decodeCount >= alias_ratio_range_high: 469 // allow 10% to come from alias expansion for very large documents 470 return 0.10 471 default: 472 // scale smoothly from 99% down to 10% over the range. 473 // this maps to 396,000 - 400,000 allowed alias-driven decodes over the range. 474 // 400,000 decode operations is ~100MB of allocations in worst-case scenarios (single-item maps). 475 return 0.99 - 0.89*(float64(decodeCount-alias_ratio_range_low)/alias_ratio_range) 476 } 477 } 478 479 func (d *decoder) unmarshal(n *Node, out reflect.Value) (good bool) { 480 d.decodeCount++ 481 if d.aliasDepth > 0 { 482 d.aliasCount++ 483 } 484 if d.aliasCount > 100 && d.decodeCount > 1000 && float64(d.aliasCount)/float64(d.decodeCount) > allowedAliasRatio(d.decodeCount) { 485 failf("document contains excessive aliasing") 486 } 487 if out.Type() == nodeType { 488 out.Set(reflect.ValueOf(n).Elem()) 489 return true 490 } 491 switch n.Kind { 492 case DocumentNode: 493 return d.document(n, out) 494 case AliasNode: 495 return d.alias(n, out) 496 } 497 out, unmarshaled, good := d.prepare(n, out) 498 if unmarshaled { 499 return good 500 } 501 switch n.Kind { 502 case ScalarNode: 503 good = d.scalar(n, out) 504 case MappingNode: 505 good = d.mapping(n, out) 506 case SequenceNode: 507 good = d.sequence(n, out) 508 case 0: 509 if n.IsZero() { 510 return d.null(out) 511 } 512 fallthrough 513 default: 514 failf("cannot decode node with unknown kind %d", n.Kind) 515 } 516 return good 517 } 518 519 func (d *decoder) document(n *Node, out reflect.Value) (good bool) { 520 if len(n.Content) == 1 { 521 d.doc = n 522 d.unmarshal(n.Content[0], out) 523 return true 524 } 525 return false 526 } 527 528 func (d *decoder) alias(n *Node, out reflect.Value) (good bool) { 529 if d.aliases[n] { 530 // TODO this could actually be allowed in some circumstances. 531 failf("anchor '%s' value contains itself", n.Value) 532 } 533 d.aliases[n] = true 534 d.aliasDepth++ 535 good = d.unmarshal(n.Alias, out) 536 d.aliasDepth-- 537 delete(d.aliases, n) 538 return good 539 } 540 541 var zeroValue reflect.Value 542 543 func resetMap(out reflect.Value) { 544 for _, k := range out.MapKeys() { 545 out.SetMapIndex(k, zeroValue) 546 } 547 } 548 549 func (d *decoder) null(out reflect.Value) bool { 550 if out.CanAddr() { 551 switch out.Kind() { 552 case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: 553 out.Set(reflect.Zero(out.Type())) 554 return true 555 } 556 } 557 return false 558 } 559 560 func (d *decoder) scalar(n *Node, out reflect.Value) bool { 561 var tag string 562 var resolved interface{} 563 if n.indicatedString() { 564 tag = strTag 565 resolved = n.Value 566 } else { 567 tag, resolved = resolve(n.Tag, n.Value) 568 if tag == binaryTag { 569 data, err := base64.StdEncoding.DecodeString(resolved.(string)) 570 if err != nil { 571 failf("!!binary value contains invalid base64 data") 572 } 573 resolved = string(data) 574 } 575 } 576 if resolved == nil { 577 return d.null(out) 578 } 579 if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { 580 // We've resolved to exactly the type we want, so use that. 581 out.Set(resolvedv) 582 return true 583 } 584 // Perhaps we can use the value as a TextUnmarshaler to 585 // set its value. 586 if out.CanAddr() { 587 u, ok := out.Addr().Interface().(encoding.TextUnmarshaler) 588 if ok { 589 var text []byte 590 if tag == binaryTag { 591 text = []byte(resolved.(string)) 592 } else { 593 // We let any value be unmarshaled into TextUnmarshaler. 594 // That might be more lax than we'd like, but the 595 // TextUnmarshaler itself should bowl out any dubious values. 596 text = []byte(n.Value) 597 } 598 err := u.UnmarshalText(text) 599 if err != nil { 600 fail(err) 601 } 602 return true 603 } 604 } 605 switch out.Kind() { 606 case reflect.String: 607 if tag == binaryTag { 608 out.SetString(resolved.(string)) 609 return true 610 } 611 out.SetString(n.Value) 612 return true 613 case reflect.Interface: 614 out.Set(reflect.ValueOf(resolved)) 615 return true 616 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 617 // This used to work in v2, but it's very unfriendly. 618 isDuration := out.Type() == durationType 619 620 switch resolved := resolved.(type) { 621 case int: 622 if !isDuration && !out.OverflowInt(int64(resolved)) { 623 out.SetInt(int64(resolved)) 624 return true 625 } 626 case int64: 627 if !isDuration && !out.OverflowInt(resolved) { 628 out.SetInt(resolved) 629 return true 630 } 631 case uint64: 632 if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { 633 out.SetInt(int64(resolved)) 634 return true 635 } 636 case float64: 637 if !isDuration && resolved <= math.MaxInt64 && !out.OverflowInt(int64(resolved)) { 638 out.SetInt(int64(resolved)) 639 return true 640 } 641 case string: 642 if out.Type() == durationType { 643 d, err := time.ParseDuration(resolved) 644 if err == nil { 645 out.SetInt(int64(d)) 646 return true 647 } 648 } 649 } 650 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: 651 switch resolved := resolved.(type) { 652 case int: 653 if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { 654 out.SetUint(uint64(resolved)) 655 return true 656 } 657 case int64: 658 if resolved >= 0 && !out.OverflowUint(uint64(resolved)) { 659 out.SetUint(uint64(resolved)) 660 return true 661 } 662 case uint64: 663 if !out.OverflowUint(uint64(resolved)) { 664 out.SetUint(uint64(resolved)) 665 return true 666 } 667 case float64: 668 if resolved <= math.MaxUint64 && !out.OverflowUint(uint64(resolved)) { 669 out.SetUint(uint64(resolved)) 670 return true 671 } 672 } 673 case reflect.Bool: 674 switch resolved := resolved.(type) { 675 case bool: 676 out.SetBool(resolved) 677 return true 678 case string: 679 // This offers some compatibility with the 1.1 spec (https://yaml.org/type/bool.html). 680 // It only works if explicitly attempting to unmarshal into a typed bool value. 681 switch resolved { 682 case "y", "Y", "yes", "Yes", "YES", "on", "On", "ON": 683 out.SetBool(true) 684 return true 685 case "n", "N", "no", "No", "NO", "off", "Off", "OFF": 686 out.SetBool(false) 687 return true 688 } 689 } 690 case reflect.Float32, reflect.Float64: 691 switch resolved := resolved.(type) { 692 case int: 693 out.SetFloat(float64(resolved)) 694 return true 695 case int64: 696 out.SetFloat(float64(resolved)) 697 return true 698 case uint64: 699 out.SetFloat(float64(resolved)) 700 return true 701 case float64: 702 out.SetFloat(resolved) 703 return true 704 } 705 case reflect.Struct: 706 if resolvedv := reflect.ValueOf(resolved); out.Type() == resolvedv.Type() { 707 out.Set(resolvedv) 708 return true 709 } 710 case reflect.Ptr: 711 panic("yaml internal error: please report the issue") 712 } 713 d.terror(n, tag, out) 714 return false 715 } 716 717 func settableValueOf(i interface{}) reflect.Value { 718 v := reflect.ValueOf(i) 719 sv := reflect.New(v.Type()).Elem() 720 sv.Set(v) 721 return sv 722 } 723 724 func (d *decoder) sequence(n *Node, out reflect.Value) (good bool) { 725 l := len(n.Content) 726 727 var iface reflect.Value 728 switch out.Kind() { 729 case reflect.Slice: 730 out.Set(reflect.MakeSlice(out.Type(), l, l)) 731 case reflect.Array: 732 if l != out.Len() { 733 failf("invalid array: want %d elements but got %d", out.Len(), l) 734 } 735 case reflect.Interface: 736 // No type hints. Will have to use a generic sequence. 737 iface = out 738 out = settableValueOf(make([]interface{}, l)) 739 default: 740 d.terror(n, seqTag, out) 741 return false 742 } 743 et := out.Type().Elem() 744 745 j := 0 746 for i := 0; i < l; i++ { 747 e := reflect.New(et).Elem() 748 if ok := d.unmarshal(n.Content[i], e); ok { 749 out.Index(j).Set(e) 750 j++ 751 } 752 } 753 if out.Kind() != reflect.Array { 754 out.Set(out.Slice(0, j)) 755 } 756 if iface.IsValid() { 757 iface.Set(out) 758 } 759 return true 760 } 761 762 func (d *decoder) mapping(n *Node, out reflect.Value) (good bool) { 763 l := len(n.Content) 764 if d.uniqueKeys { 765 nerrs := len(d.terrors) 766 for i := 0; i < l; i += 2 { 767 ni := n.Content[i] 768 for j := i + 2; j < l; j += 2 { 769 nj := n.Content[j] 770 if ni.Kind == nj.Kind && ni.Value == nj.Value { 771 d.terrors = append(d.terrors, fmt.Sprintf("line %d: mapping key %#v already defined at line %d", nj.Line, nj.Value, ni.Line)) 772 } 773 } 774 } 775 if len(d.terrors) > nerrs { 776 return false 777 } 778 } 779 switch out.Kind() { 780 case reflect.Struct: 781 return d.mappingStruct(n, out) 782 case reflect.Map: 783 // okay 784 case reflect.Interface: 785 iface := out 786 if isStringMap(n) { 787 out = reflect.MakeMap(d.stringMapType) 788 } else { 789 out = reflect.MakeMap(d.generalMapType) 790 } 791 iface.Set(out) 792 default: 793 d.terror(n, mapTag, out) 794 return false 795 } 796 797 outt := out.Type() 798 kt := outt.Key() 799 et := outt.Elem() 800 801 stringMapType := d.stringMapType 802 generalMapType := d.generalMapType 803 if outt.Elem() == ifaceType { 804 if outt.Key().Kind() == reflect.String { 805 d.stringMapType = outt 806 } else if outt.Key() == ifaceType { 807 d.generalMapType = outt 808 } 809 } 810 811 mapIsNew := false 812 if out.IsNil() { 813 out.Set(reflect.MakeMap(outt)) 814 mapIsNew = true 815 } 816 for i := 0; i < l; i += 2 { 817 if isMerge(n.Content[i]) { 818 d.merge(n.Content[i+1], out) 819 continue 820 } 821 k := reflect.New(kt).Elem() 822 if d.unmarshal(n.Content[i], k) { 823 kkind := k.Kind() 824 if kkind == reflect.Interface { 825 kkind = k.Elem().Kind() 826 } 827 if kkind == reflect.Map || kkind == reflect.Slice { 828 failf("invalid map key: %#v", k.Interface()) 829 } 830 e := reflect.New(et).Elem() 831 if d.unmarshal(n.Content[i+1], e) || n.Content[i+1].ShortTag() == nullTag && (mapIsNew || !out.MapIndex(k).IsValid()) { 832 out.SetMapIndex(k, e) 833 } 834 } 835 } 836 d.stringMapType = stringMapType 837 d.generalMapType = generalMapType 838 return true 839 } 840 841 func isStringMap(n *Node) bool { 842 if n.Kind != MappingNode { 843 return false 844 } 845 l := len(n.Content) 846 for i := 0; i < l; i += 2 { 847 if n.Content[i].ShortTag() != strTag { 848 return false 849 } 850 } 851 return true 852 } 853 854 func (d *decoder) mappingStruct(n *Node, out reflect.Value) (good bool) { 855 sinfo, err := getStructInfo(out.Type()) 856 if err != nil { 857 panic(err) 858 } 859 860 var inlineMap reflect.Value 861 var elemType reflect.Type 862 if sinfo.InlineMap != -1 { 863 inlineMap = out.Field(sinfo.InlineMap) 864 inlineMap.Set(reflect.New(inlineMap.Type()).Elem()) 865 elemType = inlineMap.Type().Elem() 866 } 867 868 for _, index := range sinfo.InlineUnmarshalers { 869 field := d.fieldByIndex(n, out, index) 870 d.prepare(n, field) 871 } 872 873 var doneFields []bool 874 if d.uniqueKeys { 875 doneFields = make([]bool, len(sinfo.FieldsList)) 876 } 877 name := settableValueOf("") 878 l := len(n.Content) 879 for i := 0; i < l; i += 2 { 880 ni := n.Content[i] 881 if isMerge(ni) { 882 d.merge(n.Content[i+1], out) 883 continue 884 } 885 if !d.unmarshal(ni, name) { 886 continue 887 } 888 if info, ok := sinfo.FieldsMap[name.String()]; ok { 889 if d.uniqueKeys { 890 if doneFields[info.Id] { 891 d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s already set in type %s", ni.Line, name.String(), out.Type())) 892 continue 893 } 894 doneFields[info.Id] = true 895 } 896 var field reflect.Value 897 if info.Inline == nil { 898 field = out.Field(info.Num) 899 } else { 900 field = d.fieldByIndex(n, out, info.Inline) 901 } 902 d.unmarshal(n.Content[i+1], field) 903 } else if sinfo.InlineMap != -1 { 904 if inlineMap.IsNil() { 905 inlineMap.Set(reflect.MakeMap(inlineMap.Type())) 906 } 907 value := reflect.New(elemType).Elem() 908 d.unmarshal(n.Content[i+1], value) 909 inlineMap.SetMapIndex(name, value) 910 } else if d.knownFields { 911 d.terrors = append(d.terrors, fmt.Sprintf("line %d: field %s not found in type %s", ni.Line, name.String(), out.Type())) 912 } 913 } 914 return true 915 } 916 917 func failWantMap() { 918 failf("map merge requires map or sequence of maps as the value") 919 } 920 921 func (d *decoder) merge(n *Node, out reflect.Value) { 922 switch n.Kind { 923 case MappingNode: 924 d.unmarshal(n, out) 925 case AliasNode: 926 if n.Alias != nil && n.Alias.Kind != MappingNode { 927 failWantMap() 928 } 929 d.unmarshal(n, out) 930 case SequenceNode: 931 // Step backwards as earlier nodes take precedence. 932 for i := len(n.Content) - 1; i >= 0; i-- { 933 ni := n.Content[i] 934 if ni.Kind == AliasNode { 935 if ni.Alias != nil && ni.Alias.Kind != MappingNode { 936 failWantMap() 937 } 938 } else if ni.Kind != MappingNode { 939 failWantMap() 940 } 941 d.unmarshal(ni, out) 942 } 943 default: 944 failWantMap() 945 } 946 } 947 948 func isMerge(n *Node) bool { 949 return n.Kind == ScalarNode && n.Value == "<<" && (n.Tag == "" || n.Tag == "!" || shortTag(n.Tag) == mergeTag) 950 }