11 "github.com/hashicorp/hcl/hcl/ast"
12 "github.com/hashicorp/hcl/hcl/parser"
13 "github.com/hashicorp/hcl/hcl/token"
16 // This is the tag to use with structures to have settings for HCL
20 // nodeType holds a reference to the type of ast.Node
21 nodeType reflect.Type = findNodeType()
24 // Unmarshal accepts a byte slice as input and writes the
25 // data to the value pointed to by v.
26 func Unmarshal(bs []byte, v interface{}) error {
27 root, err := parse(bs)
32 return DecodeObject(v, root)
35 // Decode reads the given input and decodes it into the structure
37 func Decode(out interface{}, in string) error {
43 return DecodeObject(out, obj)
46 // DecodeObject is a lower-level version of Decode. It decodes a
47 // raw Object into the given output.
48 func 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")
54 // If we have the file, we really decode the root node
55 if f, ok := n.(*ast.File); ok {
60 return d.decode("root", n, val.Elem())
67 func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
70 // If we have an interface with a valid value, we use that
72 if result.Kind() == reflect.Interface {
79 // Push current onto stack unless it is an interface.
80 if k.Kind() != reflect.Interface {
81 d.stack = append(d.stack, k.Kind())
85 d.stack = d.stack[:len(d.stack)-1]
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)
100 return d.decodeMap(name, node, result)
102 return d.decodePtr(name, node, result)
104 return d.decodeSlice(name, node, result)
106 return d.decodeString(name, node, result)
108 return d.decodeStruct(name, node, result)
110 return &parser.PosError{
112 Err: fmt.Errorf("%s: unknown kind to decode into: %s", name, k.Kind()),
117 func (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)
126 result.Set(reflect.ValueOf(v))
131 return &parser.PosError{
133 Err: fmt.Errorf("%s: unknown type %T", name, node),
137 func (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)
146 result.Set(reflect.ValueOf(v).Convert(result.Type()))
151 return &parser.PosError{
153 Err: fmt.Errorf("%s: unknown type %T", name, node),
157 func (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 {
162 v, err := strconv.ParseInt(n.Token.Text, 0, 0)
167 if result.Kind() == reflect.Interface {
168 result.Set(reflect.ValueOf(int(v)))
174 v, err := strconv.ParseInt(n.Token.Value().(string), 0, 0)
179 if result.Kind() == reflect.Interface {
180 result.Set(reflect.ValueOf(int(v)))
188 return &parser.PosError{
190 Err: fmt.Errorf("%s: unknown type %T", name, node),
194 func (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
198 if result.Type() == nodeType && result.CanSet() {
199 result.Set(reflect.ValueOf(node))
203 var set reflect.Value
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.
209 if ot, ok := node.(*ast.ObjectType); ok {
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
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(
224 tempVal.Type().Elem()))
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))
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
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(
244 tempVal.Type().Elem()))
248 var temp []map[string]interface{}
249 tempVal := reflect.ValueOf(temp)
250 result := reflect.MakeSlice(
251 reflect.SliceOf(tempVal.Type().Elem()), 0, 1)
255 var temp []interface{}
256 tempVal := reflect.ValueOf(temp)
257 result := reflect.MakeSlice(
258 reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
260 case *ast.LiteralType:
261 switch n.Token.Type {
264 set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
267 set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
270 set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
271 case token.STRING, token.HEREDOC:
272 set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
274 return &parser.PosError{
276 Err: fmt.Errorf("%s: cannot decode into interface: %T", name, node),
281 "%s: cannot decode into interface: %T",
285 // Set the result to what its supposed to be, then reset
286 // result so we don't reflect into this method anymore.
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 {
300 func (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}}
305 if ot, ok := node.(*ast.ObjectType); ok {
309 n, ok := node.(*ast.ObjectList)
311 return &parser.PosError{
313 Err: fmt.Errorf("%s: not an object type for map (%T)", name, node),
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
320 if result.Kind() == reflect.Interface {
321 result = result.Elem()
324 resultType := result.Type()
325 resultElemType := resultType.Elem()
326 resultKeyType := resultType.Key()
327 if resultKeyType.Kind() != reflect.String {
328 return &parser.PosError{
330 Err: fmt.Errorf("%s: map must have string keys", name),
334 // Make a map if it is nil
337 resultMap = reflect.MakeMap(
338 reflect.MapOf(resultKeyType, resultElemType))
341 // Go through each element and decode it.
342 done := make(map[string]struct{})
343 for _, item := range n.Items {
348 // github.com/hashicorp/terraform/issue/5740
349 if len(item.Keys) == 0 {
350 return &parser.PosError{
352 Err: fmt.Errorf("%s: map must have string keys", name),
356 // Get the key we're dealing with, which is the first item
357 keyStr := item.Keys[0].Token.Value().(string)
359 // If we've already processed this key, then ignore it
360 if _, ok := done[keyStr]; ok {
364 // Determine the value. If we have more than one key, then we
365 // get the objectlist of only these keys.
367 if len(item.Keys) > 1 {
368 itemVal = n.Filter(keyStr)
369 done[keyStr] = struct{}{}
372 // Make the field name
373 fieldName := fmt.Sprintf("%s.%s", name, keyStr)
375 // Get the key/value as reflection values
376 key := reflect.ValueOf(keyStr)
377 val := reflect.Indirect(reflect.New(resultElemType))
379 // If we have a pre-existing value in the map, use that
380 oldVal := resultMap.MapIndex(key)
381 if oldVal.IsValid() {
386 if err := d.decode(fieldName, itemVal, val); err != nil {
390 // Set the value on the map
391 resultMap.SetMapIndex(key, val)
394 // Set the final map if we can
399 func (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 {
413 func (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
417 if result.Kind() == reflect.Interface {
418 result = result.Elem()
420 // Create the slice if it isn't nil
421 resultType := result.Type()
422 resultElemType := resultType.Elem()
424 resultSliceType := reflect.SliceOf(resultElemType)
425 result = reflect.MakeSlice(
426 resultSliceType, 0, 0)
429 // Figure out the items we'll be copying into the slice
431 switch n := node.(type) {
432 case *ast.ObjectList:
433 items = make([]ast.Node, len(n.Items))
434 for i, item := range n.Items {
437 case *ast.ObjectType:
438 items = []ast.Node{n}
442 return &parser.PosError{
444 Err: fmt.Errorf("unknown slice type: %T", node),
448 for i, item := range items {
449 fieldName := fmt.Sprintf("%s[%d]", name, i)
452 val := reflect.Indirect(reflect.New(resultElemType))
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)
459 if err := d.decode(fieldName, item, val); err != nil {
463 // Append it onto the slice
464 result = reflect.Append(result, val)
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.
473 func expandObject(node ast.Node, result reflect.Value) ast.Node {
474 item, ok := node.(*ast.ObjectItem)
479 elemType := result.Type()
481 // our target type must be a struct
482 switch elemType.Kind() {
484 switch elemType.Elem().Kind() {
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 {
502 keyToken := item.Keys[0].Token
503 item.Keys = item.Keys[1:]
505 // we need to un-flatten the ast enough to decode
506 newNode := &ast.ObjectItem{
507 Keys: []*ast.ObjectKey{
512 Val: &ast.ObjectType{
513 List: &ast.ObjectList{
514 Items: []*ast.ObjectItem{item},
522 func (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 {
527 result.Set(reflect.ValueOf(n.Token.Text).Convert(result.Type()))
529 case token.STRING, token.HEREDOC:
530 result.Set(reflect.ValueOf(n.Token.Value()).Convert(result.Type()))
535 return &parser.PosError{
537 Err: fmt.Errorf("%s: unknown type for string %T", name, node),
541 func (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 {
548 if ot, ok := node.(*ast.ObjectType); ok {
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}}
560 list, ok := node.(*ast.ObjectList)
562 return &parser.PosError{
564 Err: fmt.Errorf("%s: not an object type for struct (%T)", name, node),
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)
574 // Compile the list of all the fields that we're going to be decoding
575 // from all the structs.
577 field reflect.StructField
581 for len(structs) > 0 {
582 structVal := structs[0]
583 structs = structs[1:]
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), ",")
590 // Ignore fields with tag name "-"
591 if tagParts[0] == "-" {
595 if fieldType.Anonymous {
596 fieldKind := fieldType.Type.Kind()
597 if fieldKind != reflect.Struct {
598 return &parser.PosError{
600 Err: fmt.Errorf("%s: unsupported type to struct: %s",
601 fieldType.Name, fieldKind),
605 // We have an embedded field. We "squash" the fields down
606 // if specified in the tag.
608 for _, tag := range tagParts[1:] {
617 structs, result.FieldByName(fieldType.Name))
622 // Normal struct field, store it away
623 fields = append(fields, field{fieldType, structVal.Field(i)})
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")
638 // If we can't set the field, then it is unexported or something,
639 // and we just continue onwards.
640 if !fieldValue.CanSet() {
644 fieldName := field.Name
646 tagValue := field.Tag.Get(tagName)
647 tagParts := strings.SplitN(tagValue, ",", 2)
648 if len(tagParts) >= 2 {
650 case "decodedFields":
651 decodedFieldsVal = append(decodedFieldsVal, fieldValue)
655 return &parser.PosError{
657 Err: fmt.Errorf("%s: %s asked for 'key', impossible",
662 fieldValue.SetString(item.Keys[0].Token.Value().(string))
665 unusedKeysVal = append(unusedKeysVal, fieldValue)
670 if tagParts[0] != "" {
671 fieldName = tagParts[0]
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)
679 prefixMatches := filter.Children()
680 matches := filter.Elem()
681 if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
685 // Track the used key
686 usedKeys[fieldName] = struct{}{}
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 {
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}
702 if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
707 decodedFields = append(decodedFields, field.Name)
710 if len(decodedFieldsVal) > 0 {
711 // Sort it so that it is deterministic
712 sort.Strings(decodedFields)
714 for _, v := range decodedFieldsVal {
715 v.Set(reflect.ValueOf(decodedFields))
722 // findNodeType returns the type of ast.Node
723 func findNodeType() reflect.Type {
724 var nodeContainer struct {
727 value := reflect.ValueOf(nodeContainer).FieldByName("Node")