1package hcl
2
3import (
4	"errors"
5	"fmt"
6	"reflect"
7	"sort"
8	"strconv"
9	"strings"
10
11	"github.com/hashicorp/hcl/hcl/ast"
12	"github.com/hashicorp/hcl/hcl/parser"
13	"github.com/hashicorp/hcl/hcl/token"
14)
15
16// This is the tag to use with structures to have settings for HCL
17const tagName = "hcl"
18
19var (
20	// nodeType holds a reference to the type of ast.Node
21	nodeType reflect.Type = findNodeType()
22)
23
24// Unmarshal accepts a byte slice as input and writes the
25// data to the value pointed to by v.
26func Unmarshal(bs []byte, v interface{}) error {
27	root, err := parse(bs)
28	if err != nil {
29		return err
30	}
31
32	return DecodeObject(v, root)
33}
34
35// Decode reads the given input and decodes it into the structure
36// given by `out`.
37func Decode(out interface{}, in string) error {
38	obj, err := Parse(in)
39	if err != nil {
40		return err
41	}
42
43	return DecodeObject(out, obj)
44}
45
46// DecodeObject is a lower-level version of Decode. It decodes a
47// raw Object into the given output.
48func DecodeObject(out interface{}, n ast.Node) error {
49	val := reflect.ValueOf(out)
50	if val.Kind() != reflect.Ptr {
51		return errors.New("result must be a pointer")
52	}
53
54	// If we have the file, we really decode the root node
55	if f, ok := n.(*ast.File); ok {
56		n = f.Node
57	}
58
59	var d decoder
60	return d.decode("root", n, val.Elem())
61}
62
63type decoder struct {
64	stack []reflect.Kind
65}
66
67func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
68	k := result
69
70	// If we have an interface with a valid value, we use that
71	// for the check.
72	if result.Kind() == reflect.Interface {
73		elem := result.Elem()
74		if elem.IsValid() {
75			k = elem
76		}
77	}
78
79	// Push current onto stack unless it is an interface.
80	if k.Kind() != reflect.Interface {
81		d.stack = append(d.stack, k.Kind())
82
83		// Schedule a pop
84		defer func() {
85			d.stack = d.stack[:len(d.stack)-1]
86		}()
87	}
88
89	switch k.Kind() {
90	case reflect.Bool:
91		return d.decodeBool(name, node, result)
92	case reflect.Float32, reflect.Float64:
93		return d.decodeFloat(name, node, result)
94	case reflect.Int, reflect.Int32, reflect.Int64:
95		return d.decodeInt(name, node, result)
96	case reflect.Interface:
97		// When we see an interface, we make our own thing
98		return d.decodeInterface(name, node, result)
99	case reflect.Map:
100		return d.decodeMap(name, node, result)
101	case reflect.Ptr:
102		return d.decodePtr(name, node, result)
103	case reflect.Slice:
104		return d.decodeSlice(name, node, result)
105	case reflect.String:
106		return d.decodeString(name, node, result)
107	case reflect.Struct:
108		return d.decodeStruct(name, node, result)
109	default:
110		return &parser.PosError{
111			Pos: node.Pos(),
112			Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
113		}
114	}
115}
116
117func (d *decoder) decodeBool(name string, node ast.Node, result reflect.Value) error {
118	switch n := node.(type) {
119	case *ast.LiteralType:
120		if n.Token.Type == token.BOOL {
121			v, err := strconv.ParseBool(n.Token.Text)
122			if err != nil {
123				return err
124			}
125
126			result.Set(reflect.ValueOf(v))
127			return nil
128		}
129	}
130
131	return &parser.PosError{
132		Pos: node.Pos(),
133		Err: fmt.Errorf("%s: unknown type %T", name, node),
134	}
135}
136
137func (d *decoder) decodeFloat(name string, node ast.Node, result reflect.Value) error {
138	switch n := node.(type) {
139	case *ast.LiteralType:
140		if n.Token.Type == token.FLOAT || n.Token.Type == token.NUMBER {
141			v, err := strconv.ParseFloat(n.Token.Text, 64)
142			if err != nil {
143				return err
144			}
145
146			result.Set(reflect.ValueOf(v).Convert(result.Type()))
147			return nil
148		}
149	}
150
151	return &parser.PosError{
152		Pos: node.Pos(),
153		Err: fmt.Errorf("%s: unknown type %T", name, node),
154	}
155}
156
157func (d *decoder) decodeInt(name string, node ast.Node, result reflect.Value) error {
158	switch n := node.(type) {
159	case *ast.LiteralType:
160		switch n.Token.Type {
161		case token.NUMBER:
162			v, err := strconv.ParseInt(n.Token.Text, 0, 0)
163			if err != nil {
164				return err
165			}
166
167			if result.Kind() == reflect.Interface {
168				result.Set(reflect.ValueOf(int(v)))
169			} else {
170				result.SetInt(v)
171			}
172			return nil
173		case token.STRING:
174			v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
175			if err != nil {
176				return err
177			}
178
179			if result.Kind() == reflect.Interface {
180				result.Set(reflect.ValueOf(int(v)))
181			} else {
182				result.SetInt(v)
183			}
184			return nil
185		}
186	}
187
188	return &parser.PosError{
189		Pos: node.Pos(),
190		Err: fmt.Errorf("%s: unknown type %T", name, node),
191	}
192}
193
194func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error {
195	// When we see an ast.Node, we retain the value to enable deferred decoding.
196	// Very useful in situations where we want to preserve ast.Node information
197	// like Pos
198	if result.Type() == nodeType && result.CanSet() {
199		result.Set(reflect.ValueOf(node))
200		return nil
201	}
202
203	var set reflect.Value
204	redecode := true
205
206	// For testing types, ObjectType should just be treated as a list. We
207	// set this to a temporary var because we want to pass in the real node.
208	testNode := node
209	if ot, ok := node.(*ast.ObjectType); ok {
210		testNode = ot.List
211	}
212
213	switch n := testNode.(type) {
214	case *ast.ObjectList:
215		// If we're at the root or we're directly within a slice, then we
216		// decode objects into map[string]interface{}, otherwise we decode
217		// them into lists.
218		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
219			var temp map[string]interface{}
220			tempVal := reflect.ValueOf(temp)
221			result := reflect.MakeMap(
222				reflect.MapOf(
223					reflect.TypeOf(""),
224					tempVal.Type().Elem()))
225
226			set = result
227		} else {
228			var temp []map[string]interface{}
229			tempVal := reflect.ValueOf(temp)
230			result := reflect.MakeSlice(
231				reflect.SliceOf(tempVal.Type().Elem()), 0, len(n.Items))
232			set = result
233		}
234	case *ast.ObjectType:
235		// If we're at the root or we're directly within a slice, then we
236		// decode objects into map[string]interface{}, otherwise we decode
237		// them into lists.
238		if len(d.stack) == 0 || d.stack[len(d.stack)-1] == reflect.Slice {
239			var temp map[string]interface{}
240			tempVal := reflect.ValueOf(temp)
241			result := reflect.MakeMap(
242				reflect.MapOf(
243					reflect.TypeOf(""),
244					tempVal.Type().Elem()))
245
246			set = result
247		} else {
248			var temp []map[string]interface{}
249			tempVal := reflect.ValueOf(temp)
250			result := reflect.MakeSlice(
251				reflect.SliceOf(tempVal.Type().Elem()), 0, 1)
252			set = result
253		}
254	case *ast.ListType:
255		var temp []interface{}
256		tempVal := reflect.ValueOf(temp)
257		result := reflect.MakeSlice(
258			reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
259		set = result
260	case *ast.LiteralType:
261		switch n.Token.Type {
262		case token.BOOL:
263			var result bool
264			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
265		case token.FLOAT:
266			var result float64
267			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
268		case token.NUMBER:
269			var result int
270			set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
271		case token.STRING, token.HEREDOC:
272			set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
273		default:
274			return &parser.PosError{
275				Pos: node.Pos(),
276				Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node),
277			}
278		}
279	default:
280		return fmt.Errorf(
281			"%s: cannot decode into interface: %T",
282			name, node)
283	}
284
285	// Set the result to what its supposed to be, then reset
286	// result so we don't reflect into this method anymore.
287	result.Set(set)
288
289	if redecode {
290		// Revisit the node so that we can use the newly instantiated
291		// thing and populate it.
292		if err := d.decode(name, node, result); err != nil {
293			return err
294		}
295	}
296
297	return nil
298}
299
300func (d *decoder) decodeMap(name string, node ast.Node, result reflect.Value) error {
301	if item, ok := node.(*ast.ObjectItem); ok {
302		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
303	}
304
305	if ot, ok := node.(*ast.ObjectType); ok {
306		node = ot.List
307	}
308
309	n, ok := node.(*ast.ObjectList)
310	if !ok {
311		return &parser.PosError{
312			Pos: node.Pos(),
313			Err: fmt.Errorf("%s: not an object type for map (%T)", name, node),
314		}
315	}
316
317	// If we have an interface, then we can address the interface,
318	// but not the slice itself, so get the element but set the interface
319	set := result
320	if result.Kind() == reflect.Interface {
321		result = result.Elem()
322	}
323
324	resultType := result.Type()
325	resultElemType := resultType.Elem()
326	resultKeyType := resultType.Key()
327	if resultKeyType.Kind() != reflect.String {
328		return &parser.PosError{
329			Pos: node.Pos(),
330			Err: fmt.Errorf("%s: map must have string keys", name),
331		}
332	}
333
334	// Make a map if it is nil
335	resultMap := result
336	if result.IsNil() {
337		resultMap = reflect.MakeMap(
338			reflect.MapOf(resultKeyType, resultElemType))
339	}
340
341	// Go through each element and decode it.
342	done := make(map[string]struct{})
343	for _, item := range n.Items {
344		if item.Val == nil {
345			continue
346		}
347
348		// github.com/hashicorp/terraform/issue/5740
349		if len(item.Keys) == 0 {
350			return &parser.PosError{
351				Pos: node.Pos(),
352				Err: fmt.Errorf("%s: map must have string keys", name),
353			}
354		}
355
356		// Get the key we're dealing with, which is the first item
357		keyStr := item.Keys[0].Token.Value().(string)
358
359		// If we've already processed this key, then ignore it
360		if _, ok := done[keyStr]; ok {
361			continue
362		}
363
364		// Determine the value. If we have more than one key, then we
365		// get the objectlist of only these keys.
366		itemVal := item.Val
367		if len(item.Keys) > 1 {
368			itemVal = n.Filter(keyStr)
369			done[keyStr] = struct{}{}
370		}
371
372		// Make the field name
373		fieldName := fmt.Sprintf("%s.%s", name, keyStr)
374
375		// Get the key/value as reflection values
376		key := reflect.ValueOf(keyStr)
377		val := reflect.Indirect(reflect.New(resultElemType))
378
379		// If we have a pre-existing value in the map, use that
380		oldVal := resultMap.MapIndex(key)
381		if oldVal.IsValid() {
382			val.Set(oldVal)
383		}
384
385		// Decode!
386		if err := d.decode(fieldName, itemVal, val); err != nil {
387			return err
388		}
389
390		// Set the value on the map
391		resultMap.SetMapIndex(key, val)
392	}
393
394	// Set the final map if we can
395	set.Set(resultMap)
396	return nil
397}
398
399func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error {
400	// Create an element of the concrete (non pointer) type and decode
401	// into that. Then set the value of the pointer to this type.
402	resultType := result.Type()
403	resultElemType := resultType.Elem()
404	val := reflect.New(resultElemType)
405	if err := d.decode(name, node, reflect.Indirect(val)); err != nil {
406		return err
407	}
408
409	result.Set(val)
410	return nil
411}
412
413func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error {
414	// If we have an interface, then we can address the interface,
415	// but not the slice itself, so get the element but set the interface
416	set := result
417	if result.Kind() == reflect.Interface {
418		result = result.Elem()
419	}
420	// Create the slice if it isn't nil
421	resultType := result.Type()
422	resultElemType := resultType.Elem()
423	if result.IsNil() {
424		resultSliceType := reflect.SliceOf(resultElemType)
425		result = reflect.MakeSlice(
426			resultSliceType, 0, 0)
427	}
428
429	// Figure out the items we'll be copying into the slice
430	var items []ast.Node
431	switch n := node.(type) {
432	case *ast.ObjectList:
433		items = make([]ast.Node, len(n.Items))
434		for i, item := range n.Items {
435			items[i] = item
436		}
437	case *ast.ObjectType:
438		items = []ast.Node{n}
439	case *ast.ListType:
440		items = n.List
441	default:
442		return &parser.PosError{
443			Pos: node.Pos(),
444			Err: fmt.Errorf("unknown slice type: %T", node),
445		}
446	}
447
448	for i, item := range items {
449		fieldName := fmt.Sprintf("%s[%d]", name, i)
450
451		// Decode
452		val := reflect.Indirect(reflect.New(resultElemType))
453
454		// if item is an object that was decoded from ambiguous JSON and
455		// flattened, make sure it's expanded if it needs to decode into a
456		// defined structure.
457		item := expandObject(item, val)
458
459		if err := d.decode(fieldName, item, val); err != nil {
460			return err
461		}
462
463		// Append it onto the slice
464		result = reflect.Append(result, val)
465	}
466
467	set.Set(result)
468	return nil
469}
470
471// expandObject detects if an ambiguous JSON object was flattened to a List which
472// should be decoded into a struct, and expands the ast to properly deocode.
473func expandObject(node ast.Node, result reflect.Value) ast.Node {
474	item, ok := node.(*ast.ObjectItem)
475	if !ok {
476		return node
477	}
478
479	elemType := result.Type()
480
481	// our target type must be a struct
482	switch elemType.Kind() {
483	case reflect.Ptr:
484		switch elemType.Elem().Kind() {
485		case reflect.Struct:
486			//OK
487		default:
488			return node
489		}
490	case reflect.Struct:
491		//OK
492	default:
493		return node
494	}
495
496	// A list value will have a key and field name. If it had more fields,
497	// it wouldn't have been flattened.
498	if len(item.Keys) != 2 {
499		return node
500	}
501
502	keyToken := item.Keys[0].Token
503	item.Keys = item.Keys[1:]
504
505	// we need to un-flatten the ast enough to decode
506	newNode := &ast.ObjectItem{
507		Keys: []*ast.ObjectKey{
508			&ast.ObjectKey{
509				Token: keyToken,
510			},
511		},
512		Val: &ast.ObjectType{
513			List: &ast.ObjectList{
514				Items: []*ast.ObjectItem{item},
515			},
516		},
517	}
518
519	return newNode
520}
521
522func (d *decoder) decodeString(name string, node ast.Node, result reflect.Value) error {
523	switch n := node.(type) {
524	case *ast.LiteralType:
525		switch n.Token.Type {
526		case token.NUMBER:
527			result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type()))
528			return nil
529		case token.STRING, token.HEREDOC:
530			result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type()))
531			return nil
532		}
533	}
534
535	return &parser.PosError{
536		Pos: node.Pos(),
537		Err: fmt.Errorf("%s: unknown type for string %T", name, node),
538	}
539}
540
541func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value) error {
542	var item *ast.ObjectItem
543	if it, ok := node.(*ast.ObjectItem); ok {
544		item = it
545		node = it.Val
546	}
547
548	if ot, ok := node.(*ast.ObjectType); ok {
549		node = ot.List
550	}
551
552	// Handle the special case where the object itself is a literal. Previously
553	// the yacc parser would always ensure top-level elements were arrays. The new
554	// parser does not make the same guarantees, thus we need to convert any
555	// top-level literal elements into a list.
556	if _, ok := node.(*ast.LiteralType); ok && item != nil {
557		node = &ast.ObjectList{Items: []*ast.ObjectItem{item}}
558	}
559
560	list, ok := node.(*ast.ObjectList)
561	if !ok {
562		return &parser.PosError{
563			Pos: node.Pos(),
564			Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node),
565		}
566	}
567
568	// This slice will keep track of all the structs we'll be decoding.
569	// There can be more than one struct if there are embedded structs
570	// that are squashed.
571	structs := make([]reflect.Value, 1, 5)
572	structs[0] = result
573
574	// Compile the list of all the fields that we're going to be decoding
575	// from all the structs.
576	type field struct {
577		field reflect.StructField
578		val   reflect.Value
579	}
580	fields := []field{}
581	for len(structs) > 0 {
582		structVal := structs[0]
583		structs = structs[1:]
584
585		structType := structVal.Type()
586		for i := 0; i < structType.NumField(); i++ {
587			fieldType := structType.Field(i)
588			tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
589
590			// Ignore fields with tag name "-"
591			if tagParts[0] == "-" {
592				continue
593			}
594
595			if fieldType.Anonymous {
596				fieldKind := fieldType.Type.Kind()
597				if fieldKind != reflect.Struct {
598					return &parser.PosError{
599						Pos: node.Pos(),
600						Err: fmt.Errorf("%s: unsupported type to struct: %s",
601							fieldType.Name, fieldKind),
602					}
603				}
604
605				// We have an embedded field. We "squash" the fields down
606				// if specified in the tag.
607				squash := false
608				for _, tag := range tagParts[1:] {
609					if tag == "squash" {
610						squash = true
611						break
612					}
613				}
614
615				if squash {
616					structs = append(
617						structs, result.FieldByName(fieldType.Name))
618					continue
619				}
620			}
621
622			// Normal struct field, store it away
623			fields = append(fields, field{fieldType, structVal.Field(i)})
624		}
625	}
626
627	usedKeys := make(map[string]struct{})
628	decodedFields := make([]string, 0, len(fields))
629	decodedFieldsVal := make([]reflect.Value, 0)
630	unusedKeysVal := make([]reflect.Value, 0)
631	for _, f := range fields {
632		field, fieldValue := f.field, f.val
633		if !fieldValue.IsValid() {
634			// This should never happen
635			panic("field is not valid")
636		}
637
638		// If we can't set the field, then it is unexported or something,
639		// and we just continue onwards.
640		if !fieldValue.CanSet() {
641			continue
642		}
643
644		fieldName := field.Name
645
646		tagValue := field.Tag.Get(tagName)
647		tagParts := strings.SplitN(tagValue, ",", 2)
648		if len(tagParts) >= 2 {
649			switch tagParts[1] {
650			case "decodedFields":
651				decodedFieldsVal = append(decodedFieldsVal, fieldValue)
652				continue
653			case "key":
654				if item == nil {
655					return &parser.PosError{
656						Pos: node.Pos(),
657						Err: fmt.Errorf("%s: %s asked for 'key', impossible",
658							name, fieldName),
659					}
660				}
661
662				fieldValue.SetString(item.Keys[0].Token.Value().(string))
663				continue
664			case "unusedKeys":
665				unusedKeysVal = append(unusedKeysVal, fieldValue)
666				continue
667			}
668		}
669
670		if tagParts[0] != "" {
671			fieldName = tagParts[0]
672		}
673
674		// Determine the element we'll use to decode. If it is a single
675		// match (only object with the field), then we decode it exactly.
676		// If it is a prefix match, then we decode the matches.
677		filter := list.Filter(fieldName)
678
679		prefixMatches := filter.Children()
680		matches := filter.Elem()
681		if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
682			continue
683		}
684
685		// Track the used key
686		usedKeys[fieldName] = struct{}{}
687
688		// Create the field name and decode. We range over the elements
689		// because we actually want the value.
690		fieldName = fmt.Sprintf("%s.%s", name, fieldName)
691		if len(prefixMatches.Items) > 0 {
692			if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil {
693				return err
694			}
695		}
696		for _, match := range matches.Items {
697			var decodeNode ast.Node = match.Val
698			if ot, ok := decodeNode.(*ast.ObjectType); ok {
699				decodeNode = &ast.ObjectList{Items: ot.List.Items}
700			}
701
702			if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
703				return err
704			}
705		}
706
707		decodedFields = append(decodedFields, field.Name)
708	}
709
710	if len(decodedFieldsVal) > 0 {
711		// Sort it so that it is deterministic
712		sort.Strings(decodedFields)
713
714		for _, v := range decodedFieldsVal {
715			v.Set(reflect.ValueOf(decodedFields))
716		}
717	}
718
719	return nil
720}
721
722// findNodeType returns the type of ast.Node
723func findNodeType() reflect.Type {
724	var nodeContainer struct {
725		Node ast.Node
726	}
727	value := reflect.ValueOf(nodeContainer).FieldByName("Node")
728	return value.Type()
729}
730