-
Notifications
You must be signed in to change notification settings - Fork 0
/
decode.go
157 lines (134 loc) · 3.42 KB
/
decode.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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package yamlkeys
import (
"fmt"
"io"
"strings"
"gopkg.in/yaml.v3"
)
func Decode(reader io.Reader) (any, error) {
var node yaml.Node
decoder := yaml.NewDecoder(reader)
if err := decoder.Decode(&node); err == nil {
return DecodeNode(&node)
} else {
return nil, WrapWithDecodeError(err)
}
}
func DecodeAll(reader io.Reader) ([]any, error) {
decoder := yaml.NewDecoder(reader)
var values []any
for {
var node yaml.Node
if err := decoder.Decode(&node); err == nil {
if value, err := DecodeNode(&node); err == nil {
values = append(values, value)
} else {
return nil, err
}
} else if err == io.EOF {
return values, nil
} else {
return nil, WrapWithDecodeError(err)
}
}
}
func DecodeString(s string) (any, error) {
return Decode(strings.NewReader(s))
}
func DecodeStringAll(s string) ([]any, error) {
return DecodeAll(strings.NewReader(s))
}
func DecodeNode(node *yaml.Node) (any, error) {
switch node.Kind {
case yaml.AliasNode:
return DecodeNode(node.Alias)
case yaml.DocumentNode:
if len(node.Content) != 1 {
panic(fmt.Sprintf("malformed YAML @%d,%d: document content count is %d", node.Line, node.Column, len(node.Content)))
}
return DecodeNode(node.Content[0])
case yaml.MappingNode:
map_ := make(Map)
mergeMap := make(Map)
// Content is a slice of pairs of key followed by value
length := len(node.Content)
if length%2 != 0 {
panic("malformed YAML map: not a list of key-value pairs")
}
for i := 0; i < length; i += 2 {
keyNode := node.Content[i]
valueNode := node.Content[i+1]
if value, err := DecodeNode(valueNode); err == nil {
if (keyNode.Kind == yaml.ScalarNode) && (keyNode.Tag == "!!merge") {
// See: https://yaml.org/type/merge.html
switch value_ := value.(type) {
case Map:
MapMerge(mergeMap, value_, false)
case Sequence:
for _, v := range value_ {
if m, ok := v.(Map); ok {
MapMerge(mergeMap, m, false)
} else {
panic(fmt.Sprintf("malformed YAML @%d,%d: merge", node.Line, node.Column))
}
}
default:
panic(fmt.Sprintf("malformed YAML @%d,%d: merge", node.Line, node.Column))
}
} else {
if key, keyData, err := DecodeKeyNode(keyNode); err == nil {
// Check for duplicate keys
if keyData == nil {
if _, ok := map_[key]; ok {
return nil, NewDuplicateKeyErrorFor(key, keyNode)
}
} else {
for k := range map_ {
if Equals(keyData, KeyData(k)) {
return nil, NewDuplicateKeyErrorFor(key, keyNode)
}
}
}
map_[key] = value
} else {
return nil, err
}
}
} else {
return nil, err
}
}
MapMerge(map_, mergeMap, false)
return map_, nil
case yaml.SequenceNode:
slice := make(Sequence, 0)
for _, childNode := range node.Content {
if value, err := DecodeNode(childNode); err == nil {
slice = append(slice, value)
} else {
return nil, err
}
}
return slice, nil
case yaml.ScalarNode:
var value any
if err := node.Decode(&value); err == nil {
return value, nil
} else {
return nil, WrapWithDecodeError(err)
}
}
panic(fmt.Sprintf("malformed YAML node: %T", node))
}
func DecodeKeyNode(node *yaml.Node) (any, any, error) {
if data, err := DecodeNode(node); err == nil {
if IsSimpleKey(data) {
return data, nil, nil
} else {
key, err := NewYAMLKey(data)
return key, data, err
}
} else {
return nil, nil, err
}
}