Handle pointers in slices

This commit is contained in:
Thomas Pelletier
2021-03-23 09:15:48 -04:00
parent e78ccff9a4
commit c6f117c45d
3 changed files with 31 additions and 2 deletions
@@ -517,7 +517,6 @@ Str = "Hello"
`) `)
func TestPointerUnmarshal(t *testing.T) { func TestPointerUnmarshal(t *testing.T) {
t.Log("TOML data:", string(pointerTestToml))
result := pointerMarshalTestStruct{} result := pointerMarshalTestStruct{}
err := toml.Unmarshal(pointerTestToml, &result) err := toml.Unmarshal(pointerTestToml, &result)
require.NoError(t, err) require.NoError(t, err)
+15 -1
View File
@@ -129,17 +129,29 @@ func ensureSlice(t target) error {
} }
case reflect.Interface: case reflect.Interface:
if f.IsNil() { if f.IsNil() {
return t.set(reflect.MakeSlice(reflect.TypeOf([]interface{}{}), 0, 0)) return t.set(reflect.MakeSlice(sliceInterfaceType, 0, 0))
} }
if f.Type().Elem().Kind() != reflect.Slice { if f.Type().Elem().Kind() != reflect.Slice {
return fmt.Errorf("interface is pointing to a %s, not a slice", f.Kind()) return fmt.Errorf("interface is pointing to a %s, not a slice", f.Kind())
} }
case reflect.Ptr:
if f.IsNil() {
ptr := reflect.New(f.Type().Elem())
err := t.set(ptr)
if err != nil {
return err
}
f = t.get()
}
return ensureSlice(valueTarget(f.Elem()))
default: default:
return fmt.Errorf("cannot initialize a slice in %s", f.Kind()) return fmt.Errorf("cannot initialize a slice in %s", f.Kind())
} }
return nil return nil
} }
var sliceInterfaceType = reflect.TypeOf([]interface{}{})
func setString(t target, v string) error { func setString(t target, v string) error {
f := t.get() f := t.get()
@@ -261,6 +273,8 @@ func pushNew(t target) (target, error) {
return nil, err return nil, err
} }
return valueTarget(t.get().Elem().Index(idx)), nil return valueTarget(t.get().Elem().Index(idx)), nil
case reflect.Ptr:
return pushNew(valueTarget(f.Elem()))
default: default:
return nil, fmt.Errorf("cannot pushNew on a %s", f.Kind()) return nil, fmt.Errorf("cannot pushNew on a %s", f.Kind())
} }
+16
View File
@@ -572,6 +572,22 @@ B = "data"`,
} }
}, },
}, },
{
desc: "slice pointer in slice pointer",
input: `A = ["Hello"]`,
gen: func() test {
type doc struct {
A *[]*string
}
hello := "Hello"
return test{
target: &doc{},
expected: &doc{
A: &[]*string{&hello},
},
}
},
},
} }
for _, e := range examples { for _, e := range examples {