Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Commit c0b259b

Browse files
committed
decode: can decode into interfaces
1 parent 2b17a35 commit c0b259b

File tree

2 files changed

+130
-0
lines changed

2 files changed

+130
-0
lines changed

decode.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ func (d *decoder) decode(name string, v *MrbValue, result reflect.Value) error {
6767
return d.decodeFloat(name, v, result)
6868
case reflect.Int:
6969
return d.decodeInt(name, v, result)
70+
case reflect.Interface:
71+
// When we see an interface, we make our own thing
72+
return d.decodeInterface(name, v, result)
7073
case reflect.Map:
7174
return d.decodeMap(name, v, result)
7275
case reflect.Ptr:
@@ -127,6 +130,60 @@ func (d *decoder) decodeInt(name string, v *MrbValue, result reflect.Value) erro
127130
return nil
128131
}
129132

133+
func (d *decoder) decodeInterface(name string, v *MrbValue, result reflect.Value) error {
134+
var set reflect.Value
135+
redecode := true
136+
137+
switch t := v.Type(); t {
138+
case TypeHash:
139+
var temp map[string]interface{}
140+
tempVal := reflect.ValueOf(temp)
141+
result := reflect.MakeMap(
142+
reflect.MapOf(
143+
reflect.TypeOf(""),
144+
tempVal.Type().Elem()))
145+
146+
set = result
147+
case TypeArray:
148+
var temp []interface{}
149+
tempVal := reflect.ValueOf(temp)
150+
result := reflect.MakeSlice(
151+
reflect.SliceOf(tempVal.Type().Elem()), 0, 0)
152+
set = result
153+
case TypeFalse:
154+
fallthrough
155+
case TypeTrue:
156+
var result bool
157+
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
158+
case TypeFixnum:
159+
var result int
160+
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
161+
case TypeFloat:
162+
var result float64
163+
set = reflect.Indirect(reflect.New(reflect.TypeOf(result)))
164+
case TypeString:
165+
set = reflect.Indirect(reflect.New(reflect.TypeOf("")))
166+
default:
167+
return fmt.Errorf(
168+
"%s: cannot decode into interface: %s",
169+
name, t)
170+
}
171+
172+
// Set the result to what its supposed to be, then reset
173+
// result so we don't reflect into this method anymore.
174+
result.Set(set)
175+
176+
if redecode {
177+
// Revisit the node so that we can use the newly instantiated
178+
// thing and populate it.
179+
if err := d.decode(name, v, result); err != nil {
180+
return err
181+
}
182+
}
183+
184+
return nil
185+
}
186+
130187
func (d *decoder) decodeMap(name string, v *MrbValue, result reflect.Value) error {
131188
if v.Type() != TypeHash {
132189
return fmt.Errorf("%s: not a hash type for map (%v)", name, v.Type())

decode_test.go

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,79 @@ func TestDecode(t *testing.T) {
137137
}
138138
}
139139

140+
func TestDecodeInterface(t *testing.T) {
141+
cases := []struct {
142+
Input string
143+
Expected interface{}
144+
}{
145+
// Booleans
146+
{
147+
"true",
148+
true,
149+
},
150+
151+
{
152+
"false",
153+
false,
154+
},
155+
156+
// Float
157+
{
158+
"1.2",
159+
float64(1.2000000476837158),
160+
},
161+
162+
// Int
163+
{
164+
"32",
165+
int(32),
166+
},
167+
168+
// Map
169+
{
170+
`{"foo" => "bar"}`,
171+
map[string]interface{}{"foo": "bar"},
172+
},
173+
174+
{
175+
`{32 => "bar"}`,
176+
map[string]interface{}{"32": "bar"},
177+
},
178+
179+
// Slice
180+
{
181+
`["foo", "bar"]`,
182+
[]interface{}{"foo", "bar"},
183+
},
184+
185+
// String
186+
{
187+
`"32"`,
188+
"32",
189+
},
190+
}
191+
192+
for _, tc := range cases {
193+
mrb := NewMrb()
194+
value, err := mrb.LoadString(tc.Input)
195+
if err != nil {
196+
mrb.Close()
197+
t.Fatalf("err: %s\n\n%s", err, tc.Input)
198+
}
199+
200+
var result interface{}
201+
err = Decode(&result, value)
202+
mrb.Close()
203+
if err != nil {
204+
t.Fatalf("err: %s", err)
205+
}
206+
207+
if !reflect.DeepEqual(result, tc.Expected) {
208+
t.Fatalf("bad: \n\n%s\n\n%#v\n\n%#v", tc.Input, result, tc.Expected)
209+
}
210+
}
211+
}
212+
140213
const testDecodeObjectMethods = `
141214
class Foo
142215
def foo

0 commit comments

Comments
 (0)