decoder.go (18320B)
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 // This is the tag to use with structures to have settings for HCL 17 const tagName = "hcl" 18 19 var ( 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. 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 // Decode reads the given input and decodes it into the structure 36 // given by `out`. 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 // 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") 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 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 // 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 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 // 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 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 // 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 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 { 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 // 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. 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 // 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 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 // 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 723 func findNodeType() reflect.Type { 724 var nodeContainer struct { 725 Node ast.Node 726 } 727 value := reflect.ValueOf(nodeContainer).FieldByName("Node") 728 return value.Type() 729 }