9 var kindToType = [reflect.String + 1]reflect.Type{
10 reflect.Bool: reflect.TypeOf(true),
11 reflect.String: reflect.TypeOf(""),
12 reflect.Float32: reflect.TypeOf(float64(1)),
13 reflect.Float64: reflect.TypeOf(float64(1)),
14 reflect.Int: reflect.TypeOf(int64(1)),
15 reflect.Int8: reflect.TypeOf(int64(1)),
16 reflect.Int16: reflect.TypeOf(int64(1)),
17 reflect.Int32: reflect.TypeOf(int64(1)),
18 reflect.Int64: reflect.TypeOf(int64(1)),
19 reflect.Uint: reflect.TypeOf(uint64(1)),
20 reflect.Uint8: reflect.TypeOf(uint64(1)),
21 reflect.Uint16: reflect.TypeOf(uint64(1)),
22 reflect.Uint32: reflect.TypeOf(uint64(1)),
23 reflect.Uint64: reflect.TypeOf(uint64(1)),
26 // typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found.
28 // string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32
29 func typeFor(k reflect.Kind) reflect.Type {
30 if k > 0 && int(k) < len(kindToType) {
36 func simpleValueCoercion(object interface{}) (interface{}, error) {
37 switch original := object.(type) {
38 case string, bool, int64, uint64, float64, time.Time:
41 return int64(original), nil
43 return int64(original), nil
45 return int64(original), nil
47 return int64(original), nil
49 return uint64(original), nil
51 return uint64(original), nil
53 return uint64(original), nil
55 return uint64(original), nil
57 return float64(original), nil
59 return original.String(), nil
61 return nil, fmt.Errorf("cannot convert type %T to Tree", object)
65 func sliceToTree(object interface{}) (interface{}, error) {
66 // arrays are a bit tricky, since they can represent either a
67 // collection of simple values, which is represented by one
68 // *tomlValue, or an array of tables, which is represented by an
71 // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
72 value := reflect.ValueOf(object)
73 insideType := value.Type().Elem()
76 insideType = reflect.ValueOf(value.Index(0).Interface()).Type()
78 if insideType.Kind() == reflect.Map {
79 // this is considered as an array of tables
80 tablesArray := make([]*Tree, 0, length)
81 for i := 0; i < length; i++ {
82 table := value.Index(i)
83 tree, err := toTree(table.Interface())
87 tablesArray = append(tablesArray, tree.(*Tree))
89 return tablesArray, nil
92 sliceType := typeFor(insideType.Kind())
94 sliceType = insideType
97 arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length)
99 for i := 0; i < length; i++ {
100 val := value.Index(i).Interface()
101 simpleValue, err := simpleValueCoercion(val)
105 arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
107 return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil
110 func toTree(object interface{}) (interface{}, error) {
111 value := reflect.ValueOf(object)
113 if value.Kind() == reflect.Map {
114 values := map[string]interface{}{}
115 keys := value.MapKeys()
116 for _, key := range keys {
117 if key.Kind() != reflect.String {
118 if _, ok := key.Interface().(string); !ok {
119 return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind())
123 v := value.MapIndex(key)
124 newValue, err := toTree(v.Interface())
128 values[key.String()] = newValue
130 return &Tree{values: values, position: Position{}}, nil
133 if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
134 return sliceToTree(object)
137 simpleValue, err := simpleValueCoercion(object)
141 return &tomlValue{value: simpleValue, position: Position{}}, nil