decoder structure for future options

This commit is contained in:
Mitchell Hashimoto 2014-08-02 22:37:58 -07:00
parent 5a08b50877
commit 58215e2ffa

View File

@ -21,10 +21,13 @@ func Decode(out interface{}, in string) error {
// DecodeAST is a lower-level version of Decode. It decodes a // DecodeAST is a lower-level version of Decode. It decodes a
// raw AST into the given output. // raw AST into the given output.
func DecodeAST(out interface{}, obj *ast.ObjectNode) error { func DecodeAST(out interface{}, obj *ast.ObjectNode) error {
return decode("root", *obj, reflect.ValueOf(out).Elem()) var d decoder
return d.decode("root", *obj, reflect.ValueOf(out).Elem())
} }
func decode(name string, n ast.Node, result reflect.Value) error { type decoder struct{}
func (d *decoder) decode(name string, n ast.Node, 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
@ -38,16 +41,16 @@ func decode(name string, n ast.Node, result reflect.Value) error {
switch k.Kind() { switch k.Kind() {
case reflect.Int: case reflect.Int:
return decodeInt(name, n, result) return d.decodeInt(name, n, 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 decodeInterface(name, n, result) return d.decodeInterface(name, n, result)
case reflect.Map: case reflect.Map:
return decodeMap(name, n, result) return d.decodeMap(name, n, result)
case reflect.Slice: case reflect.Slice:
return decodeSlice(name, n, result) return d.decodeSlice(name, n, result)
case reflect.String: case reflect.String:
return decodeString(name, n, result) return d.decodeString(name, n, result)
default: default:
return fmt.Errorf("%s: unknown kind: %s", name, result.Kind()) return fmt.Errorf("%s: unknown kind: %s", name, result.Kind())
} }
@ -55,7 +58,7 @@ func decode(name string, n ast.Node, result reflect.Value) error {
return nil return nil
} }
func decodeInt(name string, raw ast.Node, result reflect.Value) error { func (d *decoder) decodeInt(name string, raw ast.Node, result reflect.Value) error {
n, ok := raw.(ast.LiteralNode) n, ok := raw.(ast.LiteralNode)
if !ok { if !ok {
return fmt.Errorf("%s: not a literal type", name) return fmt.Errorf("%s: not a literal type", name)
@ -71,7 +74,7 @@ func decodeInt(name string, raw ast.Node, result reflect.Value) error {
return nil return nil
} }
func decodeInterface(name string, raw ast.Node, result reflect.Value) error { func (d *decoder) decodeInterface(name string, raw ast.Node, result reflect.Value) error {
var set reflect.Value var set reflect.Value
redecode := true redecode := true
@ -98,7 +101,7 @@ func decodeInterface(name string, raw ast.Node, result reflect.Value) error {
for _, elem := range n.Elem { for _, elem := range n.Elem {
raw := new(interface{}) raw := new(interface{})
err := decode( err := d.decode(
name, elem, reflect.Indirect(reflect.ValueOf(raw))) name, elem, reflect.Indirect(reflect.ValueOf(raw)))
if err != nil { if err != nil {
return err return err
@ -133,7 +136,7 @@ func decodeInterface(name string, raw ast.Node, result reflect.Value) error {
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, result); err != nil { if err := d.decode(name, raw, result); err != nil {
return err return err
} }
} }
@ -141,7 +144,7 @@ func decodeInterface(name string, raw ast.Node, result reflect.Value) error {
return nil return nil
} }
func decodeMap(name string, raw ast.Node, result reflect.Value) error { func (d *decoder) decodeMap(name string, raw ast.Node, result reflect.Value) error {
obj, ok := raw.(ast.ObjectNode) obj, ok := raw.(ast.ObjectNode)
if !ok { if !ok {
return fmt.Errorf("%s: not an object type", name) return fmt.Errorf("%s: not an object type", name)
@ -195,7 +198,7 @@ func decodeMap(name string, raw ast.Node, result reflect.Value) error {
} }
// Decode! // Decode!
if err := decode(fieldName, objValue, val); err != nil { if err := d.decode(fieldName, objValue, val); err != nil {
return err return err
} }
@ -208,7 +211,7 @@ func decodeMap(name string, raw ast.Node, result reflect.Value) error {
return nil return nil
} }
func decodeSlice(name string, raw ast.Node, result reflect.Value) error { func (d *decoder) decodeSlice(name string, raw ast.Node, result reflect.Value) error {
n, ok := raw.(ast.ListNode) n, ok := raw.(ast.ListNode)
if !ok { if !ok {
return fmt.Errorf("%s: not a list type", name) return fmt.Errorf("%s: not a list type", name)
@ -235,7 +238,7 @@ func decodeSlice(name string, raw ast.Node, result reflect.Value) error {
// Decode // Decode
val := reflect.Indirect(reflect.New(resultElemType)) val := reflect.Indirect(reflect.New(resultElemType))
if err := decode(fieldName, elem, val); err != nil { if err := d.decode(fieldName, elem, val); err != nil {
return err return err
} }
@ -247,7 +250,7 @@ func decodeSlice(name string, raw ast.Node, result reflect.Value) error {
return nil return nil
} }
func decodeString(name string, raw ast.Node, result reflect.Value) error { func (d *decoder) decodeString(name string, raw ast.Node, result reflect.Value) error {
n, ok := raw.(ast.LiteralNode) n, ok := raw.(ast.LiteralNode)
if !ok { if !ok {
return fmt.Errorf("%s: not a literal type", name) return fmt.Errorf("%s: not a literal type", name)