OSDN Git Service

Hulk did something
[bytom/vapor.git] / vendor / github.com / pelletier / go-toml / tomltree_create.go
diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create.go b/vendor/github.com/pelletier/go-toml/tomltree_create.go
new file mode 100644 (file)
index 0000000..79610e9
--- /dev/null
@@ -0,0 +1,142 @@
+package toml
+
+import (
+       "fmt"
+       "reflect"
+       "time"
+)
+
+var kindToType = [reflect.String + 1]reflect.Type{
+       reflect.Bool:    reflect.TypeOf(true),
+       reflect.String:  reflect.TypeOf(""),
+       reflect.Float32: reflect.TypeOf(float64(1)),
+       reflect.Float64: reflect.TypeOf(float64(1)),
+       reflect.Int:     reflect.TypeOf(int64(1)),
+       reflect.Int8:    reflect.TypeOf(int64(1)),
+       reflect.Int16:   reflect.TypeOf(int64(1)),
+       reflect.Int32:   reflect.TypeOf(int64(1)),
+       reflect.Int64:   reflect.TypeOf(int64(1)),
+       reflect.Uint:    reflect.TypeOf(uint64(1)),
+       reflect.Uint8:   reflect.TypeOf(uint64(1)),
+       reflect.Uint16:  reflect.TypeOf(uint64(1)),
+       reflect.Uint32:  reflect.TypeOf(uint64(1)),
+       reflect.Uint64:  reflect.TypeOf(uint64(1)),
+}
+
+// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found.
+// supported values:
+// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32
+func typeFor(k reflect.Kind) reflect.Type {
+       if k > 0 && int(k) < len(kindToType) {
+               return kindToType[k]
+       }
+       return nil
+}
+
+func simpleValueCoercion(object interface{}) (interface{}, error) {
+       switch original := object.(type) {
+       case string, bool, int64, uint64, float64, time.Time:
+               return original, nil
+       case int:
+               return int64(original), nil
+       case int8:
+               return int64(original), nil
+       case int16:
+               return int64(original), nil
+       case int32:
+               return int64(original), nil
+       case uint:
+               return uint64(original), nil
+       case uint8:
+               return uint64(original), nil
+       case uint16:
+               return uint64(original), nil
+       case uint32:
+               return uint64(original), nil
+       case float32:
+               return float64(original), nil
+       case fmt.Stringer:
+               return original.String(), nil
+       default:
+               return nil, fmt.Errorf("cannot convert type %T to Tree", object)
+       }
+}
+
+func sliceToTree(object interface{}) (interface{}, error) {
+       // arrays are a bit tricky, since they can represent either a
+       // collection of simple values, which is represented by one
+       // *tomlValue, or an array of tables, which is represented by an
+       // array of *Tree.
+
+       // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
+       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([]*Tree, 0, length)
+               for i := 0; i < length; i++ {
+                       table := value.Index(i)
+                       tree, err := toTree(table.Interface())
+                       if err != nil {
+                               return nil, err
+                       }
+                       tablesArray = append(tablesArray, tree.(*Tree))
+               }
+               return tablesArray, nil
+       }
+
+       sliceType := typeFor(insideType.Kind())
+       if sliceType == nil {
+               sliceType = insideType
+       }
+
+       arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length)
+
+       for i := 0; i < length; i++ {
+               val := value.Index(i).Interface()
+               simpleValue, err := simpleValueCoercion(val)
+               if err != nil {
+                       return nil, err
+               }
+               arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
+       }
+       return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil
+}
+
+func toTree(object interface{}) (interface{}, error) {
+       value := reflect.ValueOf(object)
+
+       if value.Kind() == reflect.Map {
+               values := map[string]interface{}{}
+               keys := value.MapKeys()
+               for _, key := range keys {
+                       if key.Kind() != reflect.String {
+                               if _, ok := key.Interface().(string); !ok {
+                                       return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind())
+                               }
+                       }
+
+                       v := value.MapIndex(key)
+                       newValue, err := toTree(v.Interface())
+                       if err != nil {
+                               return nil, err
+                       }
+                       values[key.String()] = newValue
+               }
+               return &Tree{values: values, position: Position{}}, nil
+       }
+
+       if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
+               return sliceToTree(object)
+       }
+
+       simpleValue, err := simpleValueCoercion(object)
+       if err != nil {
+               return nil, err
+       }
+       return &tomlValue{value: simpleValue, position: Position{}}, nil
+}