Skip to content

Commit

Permalink
Decode: assigned empty struct to empty defined sections (#879)
Browse files Browse the repository at this point in the history
Co-authored-by: Thomas Pelletier <thomas@pelletier.codes>
  • Loading branch information
dbarrosop and pelletier committed Jul 12, 2023
1 parent 60e4af8 commit e183db7
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 2 deletions.
1 change: 1 addition & 0 deletions ci.sh
Expand Up @@ -79,6 +79,7 @@ cover() {
go test -covermode=atomic -coverpkg=./... -coverprofile=coverage.out.tmp ./...
cat coverage.out.tmp | grep -v fuzz | grep -v testsuite | grep -v tomltestgen | grep -v gotoml-test-decoder > coverage.out
go tool cover -func=coverage.out
echo "Coverage profile for ${branch}: ${dir}/coverage.out" >&2
popd

if [ "${branch}" != "HEAD" ]; then
Expand Down
4 changes: 2 additions & 2 deletions unmarshaler.go
Expand Up @@ -1170,10 +1170,10 @@ func initAndDereferencePointer(v reflect.Value) reflect.Value {

// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
func fieldByIndex(v reflect.Value, path []int) reflect.Value {
for i, x := range path {
for _, x := range path {
v = v.Field(x)

if i < len(path)-1 && v.Kind() == reflect.Ptr {
if v.Kind() == reflect.Ptr {
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
Expand Down
102 changes: 102 additions & 0 deletions unmarshaler_test.go
Expand Up @@ -1277,6 +1277,64 @@ B = "data"`,
}
},
},
{
desc: "array table into maps with pointer on last key",
input: `[[foo]]
bar = "hello"`,
gen: func() test {
type doc struct {
Foo **[]interface{}
}
x := &[]interface{}{
map[string]interface{}{
"bar": "hello",
},
}
return test{
target: &doc{},
expected: &doc{
Foo: &x,
},
}
},
},
{
desc: "array table into maps with pointer on intermediate key",
input: `[[foo.foo2]]
bar = "hello"`,
gen: func() test {
type doc struct {
Foo **map[string]interface{}
}
x := &map[string]interface{}{
"foo2": []interface{}{
map[string]interface{}{
"bar": "hello",
},
},
}
return test{
target: &doc{},
expected: &doc{
Foo: &x,
},
}
},
},
{
desc: "array table into maps with pointer on last key with invalid leaf type",
input: `[[foo]]
bar = "hello"`,
gen: func() test {
type doc struct {
Foo **[]map[string]int
}
return test{
target: &doc{},
err: true,
}
},
},
{
desc: "unexported struct fields are ignored",
input: `foo = "bar"`,
Expand Down Expand Up @@ -3511,3 +3569,47 @@ func TestUnmarshalEmbedNonString(t *testing.T) {
require.NoError(t, err)
require.Nil(t, d.Foo)
}

func TestUnmarshal_Nil(t *testing.T) {
type Foo struct {
Foo *Foo `toml:"foo,omitempty"`
Bar *Foo `toml:"bar,omitempty"`
}

examples := []struct {
desc string
input string
expected string
err bool
}{
{
desc: "empty",
input: ``,
expected: ``,
},
{
desc: "simplest",
input: `
[foo]
[foo.foo]
`,
expected: "[foo]\n[foo.foo]\n",
},
}

for _, ex := range examples {
e := ex
t.Run(e.desc, func(t *testing.T) {
foo := Foo{}
err := toml.Unmarshal([]byte(e.input), &foo)
if e.err {
require.Error(t, err)
} else {
require.NoError(t, err)
j, err := toml.Marshal(foo)
require.NoError(t, err)
assert.Equal(t, e.expected, string(j))
}
})
}
}

0 comments on commit e183db7

Please sign in to comment.