1
0
Fork 0

feat: raw map parser.

This commit is contained in:
Fernandez Ludovic 2020-07-12 12:56:22 +02:00 committed by Traefiker Bot
parent 0186c31d59
commit c42f1b7a50
13 changed files with 901 additions and 18 deletions

View file

@ -57,6 +57,11 @@ func (m metadata) add(rootType reflect.Type, node *Node) error {
rType = rootType.Elem()
}
if rType.Kind() == reflect.Map && rType.Elem().Kind() == reflect.Interface {
addRawValue(node)
return nil
}
field, err := m.findTypedField(rType, node)
if err != nil {
return err
@ -88,6 +93,11 @@ func (m metadata) add(rootType reflect.Type, node *Node) error {
}
if fType.Kind() == reflect.Map {
if fType.Elem().Kind() == reflect.Interface {
addRawValue(node)
return nil
}
for _, child := range node.Children {
// elem is a map entry value type
elem := fType.Elem()
@ -194,3 +204,75 @@ func isSupportedType(field reflect.StructField) error {
return nil
}
/*
RawMap section
*/
func addRawValue(node *Node) {
if node.RawValue == nil {
node.RawValue = nodeToRawMap(node)
}
node.Children = nil
}
func nodeToRawMap(node *Node) map[string]interface{} {
result := map[string]interface{}{}
squashNode(node, result, true)
return result
}
func squashNode(node *Node, acc map[string]interface{}, root bool) {
if len(node.Children) == 0 {
acc[node.Name] = node.Value
return
}
// slice
if isArrayKey(node.Children[0].Name) {
var accChild []interface{}
for _, child := range node.Children {
tmp := map[string]interface{}{}
squashNode(child, tmp, false)
accChild = append(accChild, tmp[child.Name])
}
acc[node.Name] = accChild
return
}
// map
var accChild map[string]interface{}
if root {
accChild = acc
} else {
accChild = typedRawMap(acc, node.Name)
}
for _, child := range node.Children {
squashNode(child, accChild, false)
}
}
func typedRawMap(m map[string]interface{}, k string) map[string]interface{} {
if m[k] == nil {
m[k] = map[string]interface{}{}
}
r, ok := m[k].(map[string]interface{})
if !ok {
panic(fmt.Sprintf("unsupported value (key: %s): %T", k, m[k]))
}
return r
}
func isArrayKey(name string) bool {
return name[0] == '[' && name[len(name)-1] == ']'
}