...
1 package altsrc
2
3 import (
4 "fmt"
5 "reflect"
6
7 "github.com/BurntSushi/toml"
8 "github.com/urfave/cli/v2"
9 )
10
11 type tomlMap struct {
12 Map map[interface{}]interface{}
13 }
14
15 func unmarshalMap(i interface{}) (ret map[interface{}]interface{}, err error) {
16 ret = make(map[interface{}]interface{})
17 m := i.(map[string]interface{})
18 for key, val := range m {
19 v := reflect.ValueOf(val)
20 switch v.Kind() {
21 case reflect.Bool:
22 ret[key] = val.(bool)
23 case reflect.String:
24 ret[key] = val.(string)
25 case reflect.Int:
26 ret[key] = val.(int)
27 case reflect.Int8:
28 ret[key] = int(val.(int8))
29 case reflect.Int16:
30 ret[key] = int(val.(int16))
31 case reflect.Int32:
32 ret[key] = int(val.(int32))
33 case reflect.Int64:
34 ret[key] = int(val.(int64))
35 case reflect.Uint:
36 ret[key] = int(val.(uint))
37 case reflect.Uint8:
38 ret[key] = int(val.(uint8))
39 case reflect.Uint16:
40 ret[key] = int(val.(uint16))
41 case reflect.Uint32:
42 ret[key] = int(val.(uint32))
43 case reflect.Uint64:
44 ret[key] = int(val.(uint64))
45 case reflect.Float32:
46 ret[key] = float64(val.(float32))
47 case reflect.Float64:
48 ret[key] = val.(float64)
49 case reflect.Map:
50 if tmp, err := unmarshalMap(val); err == nil {
51 ret[key] = tmp
52 } else {
53 return nil, err
54 }
55 case reflect.Array, reflect.Slice:
56 ret[key] = val.([]interface{})
57 default:
58 return nil, fmt.Errorf("Unsupported: type = %#v", v.Kind())
59 }
60 }
61 return ret, nil
62 }
63
64 func (tm *tomlMap) UnmarshalTOML(i interface{}) error {
65 if tmp, err := unmarshalMap(i); err == nil {
66 tm.Map = tmp
67 } else {
68 return err
69 }
70 return nil
71 }
72
73 type tomlSourceContext struct {
74 FilePath string
75 }
76
77
78 func NewTomlSourceFromFile(file string) (InputSourceContext, error) {
79 tsc := &tomlSourceContext{FilePath: file}
80 var results tomlMap = tomlMap{}
81 if err := readCommandToml(tsc.FilePath, &results); err != nil {
82 return nil, fmt.Errorf("Unable to load TOML file '%s': inner error: \n'%v'", tsc.FilePath, err.Error())
83 }
84 return &MapInputSource{file: file, valueMap: results.Map}, nil
85 }
86
87
88 func NewTomlSourceFromFlagFunc(flagFileName string) func(cCtx *cli.Context) (InputSourceContext, error) {
89 return func(cCtx *cli.Context) (InputSourceContext, error) {
90 if cCtx.IsSet(flagFileName) {
91 filePath := cCtx.String(flagFileName)
92 return NewTomlSourceFromFile(filePath)
93 }
94
95 return defaultInputSource()
96 }
97 }
98
99 func readCommandToml(filePath string, container interface{}) (err error) {
100 b, err := loadDataFrom(filePath)
101 if err != nil {
102 return err
103 }
104
105 err = toml.Unmarshal(b, container)
106 if err != nil {
107 return err
108 }
109
110 err = nil
111 return
112 }
113
View as plain text