update decoder to be better interface-aware
This commit is contained in:
parent
1879551ff7
commit
dec60315c8
31
decoder.go
31
decoder.go
@ -63,7 +63,7 @@ func decodeInt(name string, raw ast.Node, result reflect.Value) error {
|
|||||||
|
|
||||||
switch n.Type {
|
switch n.Type {
|
||||||
case ast.ValueTypeInt:
|
case ast.ValueTypeInt:
|
||||||
result.SetInt(int64(n.Value.(int)))
|
result.Set(reflect.ValueOf(int64(n.Value.(int))))
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%s: unknown type %s", name, n.Type)
|
return fmt.Errorf("%s: unknown type %s", name, n.Type)
|
||||||
}
|
}
|
||||||
@ -86,6 +86,13 @@ func decodeInterface(name string, raw ast.Node, result reflect.Value) error {
|
|||||||
|
|
||||||
set = result
|
set = result
|
||||||
case ast.ListNode:
|
case ast.ListNode:
|
||||||
|
/*
|
||||||
|
var temp []interface{}
|
||||||
|
tempVal := reflect.ValueOf(temp)
|
||||||
|
result := reflect.MakeSlice(
|
||||||
|
reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
|
||||||
|
set = result
|
||||||
|
*/
|
||||||
redecode = false
|
redecode = false
|
||||||
result := make([]interface{}, 0, len(n.Elem))
|
result := make([]interface{}, 0, len(n.Elem))
|
||||||
|
|
||||||
@ -119,17 +126,18 @@ func decodeInterface(name string, raw ast.Node, result reflect.Value) error {
|
|||||||
name, raw)
|
name, raw)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the result to what its supposed to be, then reset
|
||||||
|
// result so we don't reflect into this method anymore.
|
||||||
|
result.Set(set)
|
||||||
|
|
||||||
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 := decode(name, raw, set); err != nil {
|
if err := decode(name, raw, result); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the result to what its supposed to be, then reset
|
|
||||||
// result so we don't reflect into this method anymore.
|
|
||||||
result.Set(set)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +147,13 @@ func decodeMap(name string, raw ast.Node, result reflect.Value) error {
|
|||||||
return fmt.Errorf("%s: not an object type", name)
|
return fmt.Errorf("%s: not an object type", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we have an interface, then we can address the interface,
|
||||||
|
// but not the slice itself, so get the element but set the interface
|
||||||
|
set := result
|
||||||
|
if result.Kind() == reflect.Interface {
|
||||||
|
result = result.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
resultType := result.Type()
|
resultType := result.Type()
|
||||||
resultElemType := resultType.Elem()
|
resultElemType := resultType.Elem()
|
||||||
resultKeyType := resultType.Key()
|
resultKeyType := resultType.Key()
|
||||||
@ -189,9 +204,7 @@ func decodeMap(name string, raw ast.Node, result reflect.Value) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the final map if we can
|
// Set the final map if we can
|
||||||
if result.CanAddr() {
|
set.Set(resultMap)
|
||||||
result.Set(resultMap)
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,7 +255,7 @@ func decodeString(name string, raw ast.Node, result reflect.Value) error {
|
|||||||
|
|
||||||
switch n.Type {
|
switch n.Type {
|
||||||
case ast.ValueTypeString:
|
case ast.ValueTypeString:
|
||||||
result.SetString(n.Value.(string))
|
result.Set(reflect.ValueOf(n.Value.(string)))
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%s: unknown type %s", name, n.Type)
|
return fmt.Errorf("%s: unknown type %s", name, n.Type)
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ func TestDecode(t *testing.T) {
|
|||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
"structure.hcl",
|
"structure.hcl",
|
||||||
false,
|
false,
|
||||||
@ -28,14 +29,15 @@ func TestDecode(t *testing.T) {
|
|||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"baz": []interface{}{
|
"baz": []interface{}{
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"key": 7,
|
|
||||||
"foo": "bar",
|
"foo": "bar",
|
||||||
|
"key": 7,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range cases {
|
for _, tc := range cases {
|
||||||
@ -51,7 +53,7 @@ func TestDecode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(out, tc.Out) {
|
if !reflect.DeepEqual(out, tc.Out) {
|
||||||
t.Fatalf("Input: %s\n\n%#v", tc.File, out)
|
t.Fatalf("Input: %s\n\n%#v\n\n%#v", tc.File, out, tc.Out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user