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