...

Source file src/sigs.k8s.io/yaml/goyaml.v2/decode.go

Documentation: sigs.k8s.io/yaml/goyaml.v2

     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  }
   816  

View as plain text