Skip to content

Commit

Permalink
Add support marshaling struct pointers (#16)
Browse files Browse the repository at this point in the history
This deals with two cases: where we have been provided with a pointer to
a struct in the call to Marshal(), and also where we encounter a pointer
while encoding a struct. The former case resulted in a panic (see #13),
while the latter reported that Pointer types were not supported. The
solution uses reflection to continually walk across pointers to get to
the underlying value.

Fixes #13
  • Loading branch information
timraymond authored and fjl committed Mar 10, 2017
1 parent 4c9219e commit 7a3d4a6
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 0 deletions.
12 changes: 12 additions & 0 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ type Marshaler interface {

func marshal(buf []byte, prefix string, rv reflect.Value, inArray, arrayTable bool) ([]byte, error) {
rt := rv.Type()
for rt.Kind() == reflect.Ptr {
rv = rv.Elem()
rt = rv.Type()
}

for i := 0; i < rv.NumField(); i++ {
ft := rt.Field(i)
if !ast.IsExported(ft.Name) {
Expand Down Expand Up @@ -163,6 +168,13 @@ func encodeValue(buf []byte, prefix, name string, fv reflect.Value, inArray, arr
return nil, err
}
return appendNewline(buf, inArray, arrayTable), nil
case reflect.Ptr:
newElem := fv.Elem()
if newElem.IsValid() {
return encodeValue(buf, prefix, name, newElem, inArray, arrayTable)
} else {
return encodeValue(buf, prefix, name, reflect.New(fv.Type().Elem()), inArray, arrayTable)
}
}
return nil, fmt.Errorf("toml: marshal: unsupported type %v", fv.Kind())
}
Expand Down
32 changes: 32 additions & 0 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -296,3 +296,35 @@ name="plantain"
}
}
}

func TestMarshalPointer(t *testing.T) {
type Profession struct {
Name string
Department string
}

foo := struct {
Active bool
Name string
Occupation *Profession
}{
true,
"Foo Bar",
&Profession{"Professor", "CS"},
}

expect := `active=true
name="Foo Bar"
[occupation]
name="Professor"
department="CS"
`
actual, err := toml.Marshal(&foo)
if err != nil {
t.Errorf(`Unable to marshal pointer, err was %s`, err.Error())
}

if !reflect.DeepEqual(string(actual), expect) {
t.Errorf(`Marshal(%#v); v => %#v; want %#v`, foo, string(actual), expect)
}
}

0 comments on commit 7a3d4a6

Please sign in to comment.