From f6e7596e8daafd44dc9e5c208dc73035020c8481 Mon Sep 17 00:00:00 2001 From: Thomas Pelletier Date: Thu, 23 Mar 2017 11:20:46 +0100 Subject: [PATCH] Reflect actual slice type in TreeFromMap (#145) * Reflect actual slice type in TreeFromMap * Fix writeTo for slices tomlValues Fixes #143 --- tomltree_create.go | 3 +++ tomltree_create_test.go | 27 ++++++++++++++++++++++++--- tomltree_write.go | 13 +++++++++---- tomltree_write_test.go | 13 ------------- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/tomltree_create.go b/tomltree_create.go index c9e8b37..c6054f3 100644 --- a/tomltree_create.go +++ b/tomltree_create.go @@ -65,6 +65,9 @@ func sliceToTree(object interface{}) (interface{}, error) { value := reflect.ValueOf(object) insideType := value.Type().Elem() length := value.Len() + if length > 0 { + insideType = reflect.ValueOf(value.Index(0).Interface()).Type() + } if insideType.Kind() == reflect.Map { // this is considered as an array of tables tablesArray := make([]*TomlTree, 0, length) diff --git a/tomltree_create_test.go b/tomltree_create_test.go index 74bde9e..6c14968 100644 --- a/tomltree_create_test.go +++ b/tomltree_create_test.go @@ -3,6 +3,7 @@ package toml import ( "testing" "time" + "strconv" ) type customString string @@ -21,20 +22,19 @@ func validate(t *testing.T, path string, object interface{}) { } case []*TomlTree: for index, tree := range o { - validate(t, path+"."+string(index), tree) + validate(t, path+"."+strconv.Itoa(index), tree) } case *tomlValue: switch o.value.(type) { case int64, uint64, bool, string, float64, time.Time, []int64, []uint64, []bool, []string, []float64, []time.Time: - return // ok default: t.Fatalf("tomlValue at key %s containing incorrect type %T", path, o.value) } default: t.Fatalf("value at key %s is of incorrect type %T", path, object) } - t.Log("validation ok", path) + t.Logf("validation ok %s as %T", path, object) } func validateTree(t *testing.T, tree *TomlTree) { @@ -103,3 +103,24 @@ func TestTomlTreeCreateToTreeInvalidTableGroupType(t *testing.T) { t.Fatalf("expected error %s, got %s", expected, err.Error()) } } + +func TestRoundTripArrayOfTables(t *testing.T) { + orig := "\n[[stuff]]\n name = \"foo\"\n things = [\"a\",\"b\"]\n" + tree, err := Load(orig) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + + m := tree.ToMap() + + tree, err = TreeFromMap(m) + if err != nil { + t.Fatalf("unexpected error: %s", err) + } + want := orig + got := tree.String() + + if got != want { + t.Errorf("want:\n%s\ngot:\n%s", want, got) + } +} diff --git a/tomltree_write.go b/tomltree_write.go index b50b549..89c3c42 100644 --- a/tomltree_write.go +++ b/tomltree_write.go @@ -8,6 +8,7 @@ import ( "strconv" "strings" "time" + "reflect" ) // encodes a string to a TOML-compliant string value @@ -60,9 +61,14 @@ func tomlValueStringRepresentation(v interface{}) (string, error) { return value.Format(time.RFC3339), nil case nil: return "", nil - case []interface{}: + } + + rv := reflect.ValueOf(v) + + if rv.Kind() == reflect.Slice { values := []string{} - for _, item := range value { + for i := 0; i < rv.Len(); i++ { + item := rv.Index(i).Interface() itemRepr, err := tomlValueStringRepresentation(item) if err != nil { return "", err @@ -70,9 +76,8 @@ func tomlValueStringRepresentation(v interface{}) (string, error) { values = append(values, itemRepr) } return "[" + strings.Join(values, ",") + "]", nil - default: - return "", fmt.Errorf("unsupported value type %T: %v", value, value) } + return "", fmt.Errorf("unsupported value type %T: %v", v, v) } func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) { diff --git a/tomltree_write_test.go b/tomltree_write_test.go index 6344b1c..b5ad8db 100644 --- a/tomltree_write_test.go +++ b/tomltree_write_test.go @@ -119,19 +119,6 @@ func testMaps(t *testing.T, actual, expected map[string]interface{}) { } } -func TestToTomlStringTypeConversionError(t *testing.T) { - tree := TomlTree{ - values: map[string]interface{}{ - "thing": &tomlValue{[]string{"unsupported"}, Position{}}, - }, - } - _, err := tree.ToTomlString() - expected := errors.New("unsupported value type []string: [unsupported]") - if err.Error() != expected.Error() { - t.Errorf("expecting error %s, but got %s instead", expected, err) - } -} - func TestTomlTreeWriteToMapSimple(t *testing.T) { tree, _ := Load("a = 42\nb = 17")