Skip to content

Commit

Permalink
Decode: fix decode into unsettable structs (#868)
Browse files Browse the repository at this point in the history
Fixes #866
  • Loading branch information
pelletier committed May 16, 2023
1 parent 8c2c9cc commit 986afff
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 0 deletions.
13 changes: 13 additions & 0 deletions unmarshaler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1092,6 +1092,19 @@ func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node
d.errorContext.Field = path

f := fieldByIndex(v, path)

if !f.CanSet() {
// If the field is not settable, need to take a slower path and make a copy of
// the struct itself to a new location.
nvp := reflect.New(v.Type())
nvp.Elem().Set(v)
v = nvp.Elem()
_, err := d.handleKeyValuePart(key, value, v)
if err != nil {
return reflect.Value{}, err
}
return nvp.Elem(), nil
}
x, err := d.handleKeyValueInner(key, value, f)
if err != nil {
return reflect.Value{}, err
Expand Down
64 changes: 64 additions & 0 deletions unmarshaler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,70 @@ func TestIssue851(t *testing.T) {
require.Equal(t, map[string]string{"a": "1", "b": "2"}, target.Params)
}

func TestIssue866(t *testing.T) {
type Pipeline struct {
Mapping map[string]struct {
Req [][]string `toml:"req"`
Res [][]string `toml:"res"`
} `toml:"mapping"`
}

type Pipelines struct {
PipelineMapping map[string]*Pipeline `toml:"pipelines"`
}

var badToml = `
[pipelines.register]
mapping.inst.req = [
["param1", "value1"],
]
mapping.inst.res = [
["param2", "value2"],
]
`

pipelines := new(Pipelines)
if err := toml.NewDecoder(bytes.NewBufferString(badToml)).DisallowUnknownFields().Decode(pipelines); err != nil {
t.Fatal(err)
}
if pipelines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
t.Fatal("unmarshal failed with mismatch value")
}

var goodTooToml = `
[pipelines.register]
mapping.inst.req = [
["param1", "value1"],
]
`

pipelines = new(Pipelines)
if err := toml.NewDecoder(bytes.NewBufferString(goodTooToml)).DisallowUnknownFields().Decode(pipelines); err != nil {
t.Fatal(err)
}
if pipelines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
t.Fatal("unmarshal failed with mismatch value")
}

var goodToml = `
[pipelines.register.mapping.inst]
req = [
["param1", "value1"],
]
res = [
["param2", "value2"],
]
`

pipelines = new(Pipelines)
if err := toml.NewDecoder(bytes.NewBufferString(goodToml)).DisallowUnknownFields().Decode(pipelines); err != nil {
t.Fatal(err)
}
if pipelines.PipelineMapping["register"].Mapping["inst"].Req[0][0] != "param1" {
t.Fatal("unmarshal failed with mismatch value")
}
}

func TestUnmarshalDecodeErrors(t *testing.T) {
examples := []struct {
desc string
Expand Down

0 comments on commit 986afff

Please sign in to comment.