Reflect actual slice type in TreeFromMap (#145)
* Reflect actual slice type in TreeFromMap * Fix writeTo for slices tomlValues Fixes #143
This commit is contained in:
@@ -65,6 +65,9 @@ func sliceToTree(object interface{}) (interface{}, error) {
|
|||||||
value := reflect.ValueOf(object)
|
value := reflect.ValueOf(object)
|
||||||
insideType := value.Type().Elem()
|
insideType := value.Type().Elem()
|
||||||
length := value.Len()
|
length := value.Len()
|
||||||
|
if length > 0 {
|
||||||
|
insideType = reflect.ValueOf(value.Index(0).Interface()).Type()
|
||||||
|
}
|
||||||
if insideType.Kind() == reflect.Map {
|
if insideType.Kind() == reflect.Map {
|
||||||
// this is considered as an array of tables
|
// this is considered as an array of tables
|
||||||
tablesArray := make([]*TomlTree, 0, length)
|
tablesArray := make([]*TomlTree, 0, length)
|
||||||
|
|||||||
+24
-3
@@ -3,6 +3,7 @@ package toml
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
type customString string
|
type customString string
|
||||||
@@ -21,20 +22,19 @@ func validate(t *testing.T, path string, object interface{}) {
|
|||||||
}
|
}
|
||||||
case []*TomlTree:
|
case []*TomlTree:
|
||||||
for index, tree := range o {
|
for index, tree := range o {
|
||||||
validate(t, path+"."+string(index), tree)
|
validate(t, path+"."+strconv.Itoa(index), tree)
|
||||||
}
|
}
|
||||||
case *tomlValue:
|
case *tomlValue:
|
||||||
switch o.value.(type) {
|
switch o.value.(type) {
|
||||||
case int64, uint64, bool, string, float64, time.Time,
|
case int64, uint64, bool, string, float64, time.Time,
|
||||||
[]int64, []uint64, []bool, []string, []float64, []time.Time:
|
[]int64, []uint64, []bool, []string, []float64, []time.Time:
|
||||||
return // ok
|
|
||||||
default:
|
default:
|
||||||
t.Fatalf("tomlValue at key %s containing incorrect type %T", path, o.value)
|
t.Fatalf("tomlValue at key %s containing incorrect type %T", path, o.value)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
t.Fatalf("value at key %s is of incorrect type %T", path, object)
|
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) {
|
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())
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
+9
-4
@@ -8,6 +8,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
"reflect"
|
||||||
)
|
)
|
||||||
|
|
||||||
// encodes a string to a TOML-compliant string value
|
// 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
|
return value.Format(time.RFC3339), nil
|
||||||
case nil:
|
case nil:
|
||||||
return "", nil
|
return "", nil
|
||||||
case []interface{}:
|
}
|
||||||
|
|
||||||
|
rv := reflect.ValueOf(v)
|
||||||
|
|
||||||
|
if rv.Kind() == reflect.Slice {
|
||||||
values := []string{}
|
values := []string{}
|
||||||
for _, item := range value {
|
for i := 0; i < rv.Len(); i++ {
|
||||||
|
item := rv.Index(i).Interface()
|
||||||
itemRepr, err := tomlValueStringRepresentation(item)
|
itemRepr, err := tomlValueStringRepresentation(item)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@@ -70,9 +76,8 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
|
|||||||
values = append(values, itemRepr)
|
values = append(values, itemRepr)
|
||||||
}
|
}
|
||||||
return "[" + strings.Join(values, ",") + "]", nil
|
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) {
|
func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) {
|
||||||
|
|||||||
@@ -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) {
|
func TestTomlTreeWriteToMapSimple(t *testing.T) {
|
||||||
tree, _ := Load("a = 42\nb = 17")
|
tree, _ := Load("a = 42\nb = 17")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user