-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathyaml.go
82 lines (70 loc) · 2.58 KB
/
yaml.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
package yaml
import (
"bytes"
"fmt"
"reflect"
"github.com/coveooss/gotemplate/v3/collections"
"github.com/coveooss/gotemplate/v3/collections/implementation"
"gopkg.in/yaml.v3"
)
// Expose yaml public objects
var (
Marshal = yaml.Marshal
NewDecoder = yaml.NewDecoder
NewEncoder = yaml.NewEncoder
NativeUnmarshal = yaml.Unmarshal
)
func (l yamlList) String() string { result, _ := Marshal(l.AsArray()); return string(result) }
func (d yamlDict) String() string { result, _ := Marshal(d.AsMap()); return string(result) }
func (l yamlList) PrettyPrint() string { return l.String() }
func (d yamlDict) PrettyPrint() string { return d.String() }
func init() { collections.TypeConverters["yaml"] = Unmarshal }
// Unmarshal calls the native Unmarshal but transform the results
// to returns Dictionary and GenericList instead of go native collections.
func Unmarshal(data []byte, out interface{}) (err error) {
// Yaml does not support tab, so we replace tabs by spaces if there are
data = bytes.Replace(data, []byte("\t"), []byte(" "), -1)
if err = NativeUnmarshal(data, out); err != nil {
return
}
transform(out)
return
}
func transform(out interface{}) {
result := transformElement(reflect.ValueOf(out).Elem().Interface())
if _, isMap := out.(*map[string]interface{}); isMap {
// If the result is expected to be map[string]interface{}, we convert it back from internal dict type.
result = result.(yamlIDict).Native()
}
reflect.ValueOf(out).Elem().Set(reflect.ValueOf(result))
}
func transformElement(source interface{}) interface{} {
switch value := source.(type) {
case map[interface{}]interface{}:
result := make(map[string]interface{}, len(value))
for key, val := range value {
result[fmt.Sprint(key)] = val
}
source = result
}
if value, err := yamlHelper.TryAsDictionary(source); err == nil {
for _, key := range value.KeysAsString() {
value.Set(key, transformElement(value.Get(key)))
}
source = value
} else if value, err := yamlHelper.TryAsList(source); err == nil {
for i, sub := range value.AsArray() {
value.Set(i, transformElement(sub))
}
source = value
}
return source
}
type (
helperBase = implementation.BaseHelper
helperList = implementation.ListHelper
helperDict = implementation.DictHelper
)
var needConversionImpl = implementation.NeedConversion
//go:generate genny -pkg=yaml -in=../collections/implementation/generic.go -out=generated_impl.go gen "ListTypeName=List DictTypeName=Dictionary base=yaml"
//go:generate genny -pkg=yaml -in=../collections/implementation/generic_test.go -out=generated_test.go gen "base=yaml"