compiles, all tests failing
This commit is contained in:
parent
e704c5b624
commit
f340e2e557
187
decoder.go
187
decoder.go
@ -6,7 +6,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/ast"
|
"github.com/hashicorp/hcl/hcl"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is the tag to use with structures to have settings for HCL
|
// This is the tag to use with structures to have settings for HCL
|
||||||
@ -20,19 +20,19 @@ func Decode(out interface{}, in string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return DecodeAST(out, obj)
|
return DecodeObject(out, obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DecodeAST is a lower-level version of Decode. It decodes a
|
// DecodeObject is a lower-level version of Decode. It decodes a
|
||||||
// raw AST into the given output.
|
// raw Object into the given output.
|
||||||
func DecodeAST(out interface{}, n ast.Node) error {
|
func DecodeObject(out interface{}, n *hcl.Object) error {
|
||||||
var d decoder
|
var d decoder
|
||||||
return d.decode("root", n, reflect.ValueOf(out).Elem())
|
return d.decode("root", n, reflect.ValueOf(out).Elem())
|
||||||
}
|
}
|
||||||
|
|
||||||
type decoder struct{}
|
type decoder struct{}
|
||||||
|
|
||||||
func (d *decoder) decode(name string, n ast.Node, result reflect.Value) error {
|
func (d *decoder) decode(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
k := result
|
k := result
|
||||||
|
|
||||||
// If we have an interface with a valid value, we use that
|
// If we have an interface with a valid value, we use that
|
||||||
@ -44,30 +44,24 @@ func (d *decoder) decode(name string, n ast.Node, result reflect.Value) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have a pointer, unpointer it
|
|
||||||
switch rn := n.(type) {
|
|
||||||
case *ast.ObjectNode:
|
|
||||||
n = *rn
|
|
||||||
}
|
|
||||||
|
|
||||||
switch k.Kind() {
|
switch k.Kind() {
|
||||||
case reflect.Bool:
|
case reflect.Bool:
|
||||||
return d.decodeBool(name, n, result)
|
return d.decodeBool(name, o, result)
|
||||||
case reflect.Int:
|
case reflect.Int:
|
||||||
return d.decodeInt(name, n, result)
|
return d.decodeInt(name, o, result)
|
||||||
case reflect.Interface:
|
case reflect.Interface:
|
||||||
// When we see an interface, we make our own thing
|
// When we see an interface, we make our own thing
|
||||||
return d.decodeInterface(name, n, result)
|
return d.decodeInterface(name, o, result)
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
return d.decodeMap(name, n, result)
|
return d.decodeMap(name, o, result)
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
return d.decodePtr(name, n, result)
|
return d.decodePtr(name, o, result)
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
return d.decodeSlice(name, n, result)
|
return d.decodeSlice(name, o, result)
|
||||||
case reflect.String:
|
case reflect.String:
|
||||||
return d.decodeString(name, n, result)
|
return d.decodeString(name, o, result)
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
return d.decodeStruct(name, n, result)
|
return d.decodeStruct(name, o, result)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"%s: unknown kind to decode into: %s", name, result.Kind())
|
"%s: unknown kind to decode into: %s", name, result.Kind())
|
||||||
@ -76,44 +70,34 @@ func (d *decoder) decode(name string, n ast.Node, result reflect.Value) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeBool(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeBool(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
n, ok := raw.(ast.LiteralNode)
|
switch o.Type {
|
||||||
if !ok {
|
case hcl.ValueTypeBool:
|
||||||
return fmt.Errorf("%s: not a literal type", name)
|
result.Set(reflect.ValueOf(o.Value.(bool)))
|
||||||
}
|
|
||||||
|
|
||||||
switch n.Type {
|
|
||||||
case ast.ValueTypeBool:
|
|
||||||
result.Set(reflect.ValueOf(n.Value.(bool)))
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%s: unknown type %s", name, n.Type)
|
return fmt.Errorf("%s: unknown type %s", name, o.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeInt(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeInt(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
n, ok := raw.(ast.LiteralNode)
|
switch o.Type {
|
||||||
if !ok {
|
case hcl.ValueTypeInt:
|
||||||
return fmt.Errorf("%s: not a literal type", name)
|
result.Set(reflect.ValueOf(o.Value.(int)))
|
||||||
}
|
|
||||||
|
|
||||||
switch n.Type {
|
|
||||||
case ast.ValueTypeInt:
|
|
||||||
result.Set(reflect.ValueOf(n.Value.(int)))
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%s: unknown type %s", name, n.Type)
|
return fmt.Errorf("%s: unknown type %s", name, o.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeInterface(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeInterface(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
var set reflect.Value
|
var set reflect.Value
|
||||||
redecode := true
|
redecode := true
|
||||||
|
|
||||||
switch n := raw.(type) {
|
switch o.Type {
|
||||||
case ast.ObjectNode:
|
case hcl.ValueTypeObject:
|
||||||
var temp map[string]interface{}
|
var temp map[string]interface{}
|
||||||
tempVal := reflect.ValueOf(temp)
|
tempVal := reflect.ValueOf(temp)
|
||||||
result := reflect.MakeMap(
|
result := reflect.MakeMap(
|
||||||
@ -122,7 +106,7 @@ func (d *decoder) decodeInterface(name string, raw ast.Node, result reflect.Valu
|
|||||||
tempVal.Type().Elem()))
|
tempVal.Type().Elem()))
|
||||||
|
|
||||||
set = result
|
set = result
|
||||||
case ast.ListNode:
|
case hcl.ValueTypeList:
|
||||||
/*
|
/*
|
||||||
var temp []interface{}
|
var temp []interface{}
|
||||||
tempVal := reflect.ValueOf(temp)
|
tempVal := reflect.ValueOf(temp)
|
||||||
@ -131,9 +115,10 @@ func (d *decoder) decodeInterface(name string, raw ast.Node, result reflect.Valu
|
|||||||
set = result
|
set = result
|
||||||
*/
|
*/
|
||||||
redecode = false
|
redecode = false
|
||||||
result := make([]interface{}, 0, len(n.Elem))
|
list := o.Value.([]*hcl.Object)
|
||||||
|
result := make([]interface{}, 0, len(list))
|
||||||
|
|
||||||
for _, elem := range n.Elem {
|
for _, elem := range list {
|
||||||
raw := new(interface{})
|
raw := new(interface{})
|
||||||
err := d.decode(
|
err := d.decode(
|
||||||
name, elem, reflect.Indirect(reflect.ValueOf(raw)))
|
name, elem, reflect.Indirect(reflect.ValueOf(raw)))
|
||||||
@ -145,25 +130,18 @@ func (d *decoder) decodeInterface(name string, raw ast.Node, result reflect.Valu
|
|||||||
}
|
}
|
||||||
|
|
||||||
set = reflect.ValueOf(result)
|
set = reflect.ValueOf(result)
|
||||||
case ast.LiteralNode:
|
case hcl.ValueTypeBool:
|
||||||
switch n.Type {
|
var result bool
|
||||||
case ast.ValueTypeBool:
|
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||||
var result bool
|
case hcl.ValueTypeInt:
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
var result int
|
||||||
case ast.ValueTypeInt:
|
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
||||||
var result int
|
case hcl.ValueTypeString:
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
|
set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
|
||||||
case ast.ValueTypeString:
|
|
||||||
set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
|
|
||||||
default:
|
|
||||||
return fmt.Errorf(
|
|
||||||
"%s: unknown literal type: %s",
|
|
||||||
name, n.Type)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"%s: cannot decode into interface: %T",
|
"%s: cannot decode into interface: %T",
|
||||||
name, raw)
|
name, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the result to what its supposed to be, then reset
|
// Set the result to what its supposed to be, then reset
|
||||||
@ -173,7 +151,7 @@ func (d *decoder) decodeInterface(name string, raw ast.Node, result reflect.Valu
|
|||||||
if redecode {
|
if redecode {
|
||||||
// Revisit the node so that we can use the newly instantiated
|
// Revisit the node so that we can use the newly instantiated
|
||||||
// thing and populate it.
|
// thing and populate it.
|
||||||
if err := d.decode(name, raw, result); err != nil {
|
if err := d.decode(name, o, result); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -181,23 +159,9 @@ func (d *decoder) decodeInterface(name string, raw ast.Node, result reflect.Valu
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeMap(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeMap(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
// If we have a list, then we decode each element into a map
|
if o.Type != hcl.ValueTypeObject {
|
||||||
if list, ok := raw.(ast.ListNode); ok {
|
return fmt.Errorf("%s: not an object type (%s)", name, o.Type)
|
||||||
for i, elem := range list.Elem {
|
|
||||||
fieldName := fmt.Sprintf("%s.%d", name, i)
|
|
||||||
err := d.decode(fieldName, elem, result)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
obj, ok := raw.(ast.ObjectNode)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf("%s: not an object type (%T)", name, obj)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have an interface, then we can address the interface,
|
// If we have an interface, then we can address the interface,
|
||||||
@ -223,6 +187,7 @@ func (d *decoder) decodeMap(name string, raw ast.Node, result reflect.Value) err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Go through each element and decode it.
|
// Go through each element and decode it.
|
||||||
|
/*
|
||||||
for _, n := range obj.Elem {
|
for _, n := range obj.Elem {
|
||||||
objValue := n.Value
|
objValue := n.Value
|
||||||
|
|
||||||
@ -254,19 +219,20 @@ func (d *decoder) decodeMap(name string, raw ast.Node, result reflect.Value) err
|
|||||||
// Set the value on the map
|
// Set the value on the map
|
||||||
resultMap.SetMapIndex(key, val)
|
resultMap.SetMapIndex(key, val)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
// Set the final map if we can
|
// Set the final map if we can
|
||||||
set.Set(resultMap)
|
set.Set(resultMap)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodePtr(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodePtr(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
// Create an element of the concrete (non pointer) type and decode
|
// Create an element of the concrete (non pointer) type and decode
|
||||||
// into that. Then set the value of the pointer to this type.
|
// into that. Then set the value of the pointer to this type.
|
||||||
resultType := result.Type()
|
resultType := result.Type()
|
||||||
resultElemType := resultType.Elem()
|
resultElemType := resultType.Elem()
|
||||||
val := reflect.New(resultElemType)
|
val := reflect.New(resultElemType)
|
||||||
if err := d.decode(name, raw, reflect.Indirect(val)); err != nil {
|
if err := d.decode(name, o, reflect.Indirect(val)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,13 +240,7 @@ func (d *decoder) decodePtr(name string, raw ast.Node, result reflect.Value) err
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeSlice(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeSlice(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
n, ok := raw.(ast.ListNode)
|
|
||||||
if !ok {
|
|
||||||
// If it isn't a list, we turn it into one
|
|
||||||
n = ast.ListNode{Elem: []ast.Node{raw}}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have an interface, then we can address the interface,
|
// If we have an interface, then we can address the interface,
|
||||||
// but not the slice itself, so get the element but set the interface
|
// but not the slice itself, so get the element but set the interface
|
||||||
set := result
|
set := result
|
||||||
@ -297,6 +257,7 @@ func (d *decoder) decodeSlice(name string, raw ast.Node, result reflect.Value) e
|
|||||||
resultSliceType, 0, 0)
|
resultSliceType, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
for i, elem := range n.Elem {
|
for i, elem := range n.Elem {
|
||||||
fieldName := fmt.Sprintf("%s[%d]", name, i)
|
fieldName := fmt.Sprintf("%s[%d]", name, i)
|
||||||
|
|
||||||
@ -309,48 +270,30 @@ func (d *decoder) decodeSlice(name string, raw ast.Node, result reflect.Value) e
|
|||||||
// Append it onto the slice
|
// Append it onto the slice
|
||||||
result = reflect.Append(result, val)
|
result = reflect.Append(result, val)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
set.Set(result)
|
set.Set(result)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeString(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeString(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
n, ok := raw.(ast.LiteralNode)
|
switch o.Type {
|
||||||
if !ok {
|
case hcl.ValueTypeInt:
|
||||||
return fmt.Errorf("%s: not a literal type", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch n.Type {
|
|
||||||
case ast.ValueTypeInt:
|
|
||||||
result.Set(reflect.ValueOf(
|
result.Set(reflect.ValueOf(
|
||||||
strconv.FormatInt(int64(n.Value.(int)), 10)).Convert(result.Type()))
|
strconv.FormatInt(int64(o.Value.(int)), 10)).Convert(result.Type()))
|
||||||
case ast.ValueTypeString:
|
case hcl.ValueTypeString:
|
||||||
result.Set(reflect.ValueOf(n.Value.(string)).Convert(result.Type()))
|
result.Set(reflect.ValueOf(o.Value.(string)).Convert(result.Type()))
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%s: unknown type to string: %s", name, n.Type)
|
return fmt.Errorf("%s: unknown type to string: %s", name, o.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) decodeStruct(name string, raw ast.Node, result reflect.Value) error {
|
func (d *decoder) decodeStruct(name string, o *hcl.Object, result reflect.Value) error {
|
||||||
// If we have a list, then we decode each element into a map
|
if o.Type != hcl.ValueTypeObject {
|
||||||
if list, ok := raw.(ast.ListNode); ok {
|
|
||||||
for i, elem := range list.Elem {
|
|
||||||
fieldName := fmt.Sprintf("%s.%d", name, i)
|
|
||||||
err := d.decode(fieldName, elem, result)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
obj, ok := raw.(ast.ObjectNode)
|
|
||||||
if !ok {
|
|
||||||
return fmt.Errorf(
|
return fmt.Errorf(
|
||||||
"%s: not an object type for struct (%T)", name, raw)
|
"%s: not an object type for struct (%T)", name, o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// This slice will keep track of all the structs we'll be decoding.
|
// This slice will keep track of all the structs we'll be decoding.
|
||||||
@ -401,10 +344,11 @@ func (d *decoder) decodeStruct(name string, raw ast.Node, result reflect.Value)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
usedKeys := make(map[string]struct{})
|
//usedKeys := make(map[string]struct{})
|
||||||
decodedFields := make([]string, 0, len(fields))
|
decodedFields := make([]string, 0, len(fields))
|
||||||
decodedFieldsVal := make([]reflect.Value, 0)
|
decodedFieldsVal := make([]reflect.Value, 0)
|
||||||
unusedKeysVal := make([]reflect.Value, 0)
|
unusedKeysVal := make([]reflect.Value, 0)
|
||||||
|
/*
|
||||||
for fieldType, field := range fields {
|
for fieldType, field := range fields {
|
||||||
if !field.IsValid() {
|
if !field.IsValid() {
|
||||||
// This should never happen
|
// This should never happen
|
||||||
@ -427,7 +371,7 @@ func (d *decoder) decodeStruct(name string, raw ast.Node, result reflect.Value)
|
|||||||
decodedFieldsVal = append(decodedFieldsVal, field)
|
decodedFieldsVal = append(decodedFieldsVal, field)
|
||||||
continue
|
continue
|
||||||
case "key":
|
case "key":
|
||||||
field.SetString(obj.Key())
|
field.SetString(o.Key)
|
||||||
continue
|
continue
|
||||||
case "unusedKeys":
|
case "unusedKeys":
|
||||||
unusedKeysVal = append(unusedKeysVal, field)
|
unusedKeysVal = append(unusedKeysVal, field)
|
||||||
@ -469,6 +413,7 @@ func (d *decoder) decodeStruct(name string, raw ast.Node, result reflect.Value)
|
|||||||
|
|
||||||
decodedFields = append(decodedFields, fieldType.Name)
|
decodedFields = append(decodedFields, fieldType.Name)
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
for _, v := range decodedFieldsVal {
|
for _, v := range decodedFieldsVal {
|
||||||
v.Set(reflect.ValueOf(decodedFields))
|
v.Set(reflect.ValueOf(decodedFields))
|
||||||
@ -476,6 +421,7 @@ func (d *decoder) decodeStruct(name string, raw ast.Node, result reflect.Value)
|
|||||||
|
|
||||||
// If we want to know what keys are unused, compile that
|
// If we want to know what keys are unused, compile that
|
||||||
if len(unusedKeysVal) > 0 {
|
if len(unusedKeysVal) > 0 {
|
||||||
|
/*
|
||||||
unusedKeys := make([]string, 0, int(obj.Len())-len(usedKeys))
|
unusedKeys := make([]string, 0, int(obj.Len())-len(usedKeys))
|
||||||
|
|
||||||
for _, elem := range obj.Elem {
|
for _, elem := range obj.Elem {
|
||||||
@ -492,6 +438,7 @@ func (d *decoder) decodeStruct(name string, raw ast.Node, result reflect.Value)
|
|||||||
for _, v := range unusedKeysVal {
|
for _, v := range unusedKeysVal {
|
||||||
v.Set(reflect.ValueOf(unusedKeys))
|
v.Set(reflect.ValueOf(unusedKeys))
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
5
parse.go
5
parse.go
@ -3,15 +3,14 @@ package hcl
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/hashicorp/hcl/ast"
|
|
||||||
"github.com/hashicorp/hcl/hcl"
|
"github.com/hashicorp/hcl/hcl"
|
||||||
"github.com/hashicorp/hcl/json"
|
"github.com/hashicorp/hcl/json"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Parse parses the given input and returns the root of the AST.
|
// Parse parses the given input and returns the root object.
|
||||||
//
|
//
|
||||||
// The input format can be either HCL or JSON.
|
// The input format can be either HCL or JSON.
|
||||||
func Parse(input string) (*ast.ObjectNode, error) {
|
func Parse(input string) (*hcl.Object, error) {
|
||||||
switch lexMode(input) {
|
switch lexMode(input) {
|
||||||
case lexModeHcl:
|
case lexModeHcl:
|
||||||
return hcl.Parse(input)
|
return hcl.Parse(input)
|
||||||
|
Loading…
Reference in New Issue
Block a user