1 package hcl
2
3 import (
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
17 const tagName = "hcl"
18
19 var (
20
21 nodeType reflect.Type = findNodeType()
22 )
23
24
25
26 func 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
36
37 func 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
47
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")
52 }
53
54
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
63 type decoder struct {
64 stack []reflect.Kind
65 }
66
67 func (d *decoder) decode(name string, node ast.Node, result reflect.Value) error {
68 k := result
69
70
71
72 if result.Kind() == reflect.Interface {
73 elem := result.Elem()
74 if elem.IsValid() {
75 k = elem
76 }
77 }
78
79
80 if k.Kind() != reflect.Interface {
81 d.stack = append(d.stack, k.Kind())
82
83
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
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
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)
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
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)
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
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 {
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
194 func (d *decoder) decodeInterface(name string, node ast.Node, result reflect.Value) error {
195
196
197
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
207
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
216
217
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
236
237
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
286
287 result.Set(set)
288
289 if redecode {
290
291
292 if err := d.decode(name, node, result); err != nil {
293 return err
294 }
295 }
296
297 return nil
298 }
299
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}}
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
318
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
335 resultMap := result
336 if result.IsNil() {
337 resultMap = reflect.MakeMap(
338 reflect.MapOf(resultKeyType, resultElemType))
339 }
340
341
342 done := make(map[string]struct{})
343 for _, item := range n.Items {
344 if item.Val == nil {
345 continue
346 }
347
348
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
357 keyStr := item.Keys[0].Token.Value().(string)
358
359
360 if _, ok := done[keyStr]; ok {
361 continue
362 }
363
364
365
366 itemVal := item.Val
367 if len(item.Keys) > 1 {
368 itemVal = n.Filter(keyStr)
369 done[keyStr] = struct{}{}
370 }
371
372
373 fieldName := fmt.Sprintf("%s.%s", name, keyStr)
374
375
376 key := reflect.ValueOf(keyStr)
377 val := reflect.Indirect(reflect.New(resultElemType))
378
379
380 oldVal := resultMap.MapIndex(key)
381 if oldVal.IsValid() {
382 val.Set(oldVal)
383 }
384
385
386 if err := d.decode(fieldName, itemVal, val); err != nil {
387 return err
388 }
389
390
391 resultMap.SetMapIndex(key, val)
392 }
393
394
395 set.Set(resultMap)
396 return nil
397 }
398
399 func (d *decoder) decodePtr(name string, node ast.Node, result reflect.Value) error {
400
401
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
413 func (d *decoder) decodeSlice(name string, node ast.Node, result reflect.Value) error {
414
415
416 set := result
417 if result.Kind() == reflect.Interface {
418 result = result.Elem()
419 }
420
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
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
452 val := reflect.Indirect(reflect.New(resultElemType))
453
454
455
456
457 item := expandObject(item, val)
458
459 if err := d.decode(fieldName, item, val); err != nil {
460 return err
461 }
462
463
464 result = reflect.Append(result, val)
465 }
466
467 set.Set(result)
468 return nil
469 }
470
471
472
473 func 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
482 switch elemType.Kind() {
483 case reflect.Ptr:
484 switch elemType.Elem().Kind() {
485 case reflect.Struct:
486
487 default:
488 return node
489 }
490 case reflect.Struct:
491
492 default:
493 return node
494 }
495
496
497
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
506 newNode := &ast.ObjectItem{
507 Keys: []*ast.ObjectKey{
508 {
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
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 {
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
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 {
544 item = it
545 node = it.Val
546 }
547
548 if ot, ok := node.(*ast.ObjectType); ok {
549 node = ot.List
550 }
551
552
553
554
555
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
569
570
571 structs := make([]reflect.Value, 1, 5)
572 structs[0] = result
573
574
575
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
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
606
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
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
632
633
634 unusedNodeKeys := make(map[string][]token.Pos, 0)
635 for i, item := range list.Items {
636 for _, k := range item.Keys {
637
638
639
640 isNestedJSON := i > 0 && len(item.Keys) > 1
641 if !isNestedJSON && (k.Token.JSON || k.Token.Type == token.IDENT) {
642 fn := k.Token.Value().(string)
643 sl := unusedNodeKeys[fn]
644 unusedNodeKeys[fn] = append(sl, k.Token.Pos)
645 }
646 }
647 }
648
649 for _, f := range fields {
650 field, fieldValue := f.field, f.val
651 if !fieldValue.IsValid() {
652
653 panic("field is not valid")
654 }
655
656
657
658 if !fieldValue.CanSet() {
659 continue
660 }
661
662 fieldName := field.Name
663
664 tagValue := field.Tag.Get(tagName)
665 tagParts := strings.SplitN(tagValue, ",", 2)
666 if len(tagParts) >= 2 {
667 switch tagParts[1] {
668 case "decodedFields":
669 decodedFieldsVal = append(decodedFieldsVal, fieldValue)
670 continue
671 case "key":
672 if item == nil {
673 return &parser.PosError{
674 Pos: node.Pos(),
675 Err: fmt.Errorf("%s: %s asked for 'key', impossible",
676 name, fieldName),
677 }
678 }
679
680 fieldValue.SetString(item.Keys[0].Token.Value().(string))
681 continue
682 case "unusedKeyPositions":
683 unusedKeysVal = append(unusedKeysVal, fieldValue)
684 continue
685 }
686 }
687
688 if tagParts[0] != "" {
689 fieldName = tagParts[0]
690 }
691
692
693
694
695 filter := list.Filter(fieldName)
696
697 prefixMatches := filter.Children()
698 matches := filter.Elem()
699 if len(matches.Items) == 0 && len(prefixMatches.Items) == 0 {
700 continue
701 }
702
703
704 usedKeys[fieldName] = struct{}{}
705 unusedNodeKeys = removeCaseFold(unusedNodeKeys, fieldName)
706
707
708
709 fieldName = fmt.Sprintf("%s.%s", name, fieldName)
710 if len(prefixMatches.Items) > 0 {
711 if err := d.decode(fieldName, prefixMatches, fieldValue); err != nil {
712 return err
713 }
714 }
715 for _, match := range matches.Items {
716 var decodeNode ast.Node = match.Val
717 if ot, ok := decodeNode.(*ast.ObjectType); ok {
718 decodeNode = &ast.ObjectList{Items: ot.List.Items}
719 }
720
721 if err := d.decode(fieldName, decodeNode, fieldValue); err != nil {
722 return err
723 }
724 }
725
726 decodedFields = append(decodedFields, field.Name)
727 }
728
729 if len(decodedFieldsVal) > 0 {
730
731 sort.Strings(decodedFields)
732
733 for _, v := range decodedFieldsVal {
734 v.Set(reflect.ValueOf(decodedFields))
735 }
736 }
737
738 if len(unusedNodeKeys) > 0 {
739
740 for _, v := range unusedKeysVal {
741 v.Set(reflect.ValueOf(unusedNodeKeys))
742 }
743 }
744
745 return nil
746 }
747
748
749 func findNodeType() reflect.Type {
750 var nodeContainer struct {
751 Node ast.Node
752 }
753 value := reflect.ValueOf(nodeContainer).FieldByName("Node")
754 return value.Type()
755 }
756
757 func removeCaseFold(xs map[string][]token.Pos, y string) map[string][]token.Pos {
758 var toDel []string
759
760 for i := range xs {
761 if strings.EqualFold(i, y) {
762 toDel = append(toDel, i)
763 }
764 }
765 for _, i := range toDel {
766 delete(xs, i)
767 }
768 return xs
769 }
770
View as plain text