Skip to content

Commit

Permalink
Allow decoding of nested raw typed slices
Browse files Browse the repository at this point in the history
Co-authored-by: Fernandez Ludovic <[email protected]>
  • Loading branch information
rtribotte and ldez authored Jan 20, 2023
1 parent d85e897 commit 368ce2e
Show file tree
Hide file tree
Showing 3 changed files with 115 additions and 0 deletions.
39 changes: 39 additions & 0 deletions file/file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,45 @@ meta:
}
}

func TestDecodeContent_YAML_typedSliceRecursive(t *testing.T) {
content := `
foo:
- foo
- bar
bar:
foo:
- foo
- bar
baz:
foo:
- foo
- bar
boz:
foo:
- 42
- 42
`

element := map[string]interface{}{}

err := DecodeContent(content, ".yaml", &element)
require.NoError(t, err)

expected := map[string]interface{}{
"foo": []interface{}{"foo", "bar"},
"bar": map[string]interface{}{
"foo": []interface{}{"foo", "bar"},
"baz": map[string]interface{}{
"foo": []interface{}{"foo", "bar"},
"boz": map[string]interface{}{
"foo": []interface{}{int64(42), int64(42)},
},
},
},
}
assert.Equal(t, expected, element)
}

func TestDecodeContent_JSON(t *testing.T) {
content := `
{
Expand Down
34 changes: 34 additions & 0 deletions parser/element_fill.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,12 @@ func (f filler) fillRawValue(field reflect.Value, node *Node, subMap bool) error
return nil
}

// In the case of sub-map, fill raw typed slices recursively.
_, err := f.fillRawMapWithTypedSlice(m)
if err != nil {
return err
}

p := map[string]interface{}{node.Name: m}
node.RawValue = p

Expand All @@ -428,6 +434,34 @@ func (f filler) fillRawValue(field reflect.Value, node *Node, subMap bool) error
return nil
}

func (f filler) fillRawMapWithTypedSlice(elt interface{}) (reflect.Value, error) {
eltValue := reflect.ValueOf(elt)

switch eltValue.Kind() {
case reflect.String:
if strings.HasPrefix(elt.(string), f.RawSliceSeparator) {
sliceValue, err := f.fillRawTypedSlice(elt.(string))
if err != nil {
return eltValue, err
}

return sliceValue, nil
}

case reflect.Map:
for k, v := range elt.(map[string]interface{}) {
value, err := f.fillRawMapWithTypedSlice(v)
if err != nil {
return eltValue, err
}

eltValue.SetMapIndex(reflect.ValueOf(k), value)
}
}

return eltValue, nil
}

func (f filler) fillRawTypedSlice(s string) (reflect.Value, error) {
raw := strings.Split(s, f.RawSliceSeparator)

Expand Down
42 changes: 42 additions & 0 deletions parser/element_fill_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,48 @@ func TestFill(t *testing.T) {
},
}},
},
{
desc: "recursive slices",
rawSliceSeparator: "║",
node: &Node{
Name: "traefik",
Kind: reflect.Pointer,
Children: []*Node{
{
Name: "bar",
RawValue: map[string]interface{}{
"baz": map[string]interface{}{
"boz": map[string]interface{}{
"foo": "║2║42║42",
},
"foo": "║24║foo║bar",
},
"foo": "║24║foo║bar",
},
},
{
Name: "foo",
Value: "║24║foo║bar",
RawValue: map[string]interface{}{
"foo": "║24║foo║bar",
},
},
},
},
element: &map[string]interface{}{},
expected: expected{element: &map[string]interface{}{
"foo": []interface{}{"foo", "bar"},
"bar": map[string]interface{}{
"foo": []interface{}{"foo", "bar"},
"baz": map[string]interface{}{
"foo": []interface{}{"foo", "bar"},
"boz": map[string]interface{}{
"foo": []interface{}{int64(42), int64(42)},
},
},
},
}},
},
}

for _, test := range testCases {
Expand Down

0 comments on commit 368ce2e

Please sign in to comment.