Allow unmarshal from any TomlTree (#157)

Fixes #153
This commit is contained in:
John K. Luebs
2017-05-05 19:29:08 -04:00
committed by Thomas Pelletier
parent 97253b98df
commit 53be957dac
2 changed files with 35 additions and 13 deletions
+18 -13
View File
@@ -1,6 +1,7 @@
package toml
import (
"bytes"
"errors"
"fmt"
"reflect"
@@ -224,24 +225,15 @@ func valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
}
}
/*
Unmarshal parses the TOML-encoded data and stores the result in the value
pointed to by v. Behavior is similar to the Go json encoder, except that there
is no concept of an Unmarshaler interface or UnmarshalTOML function for
sub-structs, and currently only definite types can be unmarshaled to (i.e. no
`interface{}`).
*/
func Unmarshal(data []byte, v interface{}) error {
// Unmarshal attempts to unmarshal the TomlTree into a Go struct pointed by v.
// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
// sub-structs, and only definite types can be unmarshaled.
func (t *TomlTree) Unmarshal(v interface{}) error {
mtype := reflect.TypeOf(v)
if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
return errors.New("Only a pointer to struct can be unmarshaled from TOML")
}
t, err := Load(string(data))
if err != nil {
return err
}
sval, err := valueFromTree(mtype.Elem(), t)
if err != nil {
return err
@@ -250,6 +242,19 @@ func Unmarshal(data []byte, v interface{}) error {
return nil
}
// Unmarshal parses the TOML-encoded data and stores the result in the value
// pointed to by v. Behavior is similar to the Go json encoder, except that there
// is no concept of an Unmarshaler interface or UnmarshalTOML function for
// sub-structs, and currently only definite types can be unmarshaled to (i.e. no
// `interface{}`).
func Unmarshal(data []byte, v interface{}) error {
t, err := LoadReader(bytes.NewReader(data))
if err != nil {
return err
}
return t.Unmarshal(v)
}
// Convert toml tree to marshal struct or map, using marshal type
func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) {
if mtype.Kind() == reflect.Ptr {
+17
View File
@@ -177,6 +177,23 @@ func TestDocUnmarshal(t *testing.T) {
}
}
func TestDocPartialUnmarshal(t *testing.T) {
result := testDocSubs{}
tree, _ := LoadFile("marshal_test.toml")
subTree := tree.Get("subdoc").(*TomlTree)
err := subTree.Unmarshal(&result)
expected := docData.Subdocs
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(result, expected) {
resStr, _ := json.MarshalIndent(result, "", " ")
expStr, _ := json.MarshalIndent(expected, "", " ")
t.Errorf("Bad partial unmartial: expected\n-----\n%s\n-----\ngot\n-----\n%s\n-----\n", expStr, resStr)
}
}
type tomlTypeCheckTest struct {
name string
item interface{}