Add missing UnmarshalTOML call (#996)

Fixes #994.
This commit is contained in:
Thomas Pelletier
2025-08-21 10:39:23 +02:00
committed by GitHub
parent 6d56ac8027
commit bc9958322f
2 changed files with 53 additions and 0 deletions
+11
View File
@@ -1154,6 +1154,17 @@ func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node
case reflect.Struct:
path, found := structFieldPath(v, string(key.Node().Data))
if !found {
// If no matching struct field is found but the target implements the
// unstable.Unmarshaler interface (and it is enabled), delegate the
// decoding of this value to the custom unmarshaler.
if d.unmarshalerInterface {
if v.CanAddr() && v.Addr().CanInterface() {
if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok {
return reflect.Value{}, outi.UnmarshalTOML(value)
}
}
}
// Otherwise, keep previous behavior and skip until the next table.
d.skipUntilTable = true
break
}
+42
View File
@@ -3998,3 +3998,45 @@ foo = "bar"`,
})
}
}
type doc994 struct{}
func (d *doc994) UnmarshalTOML(value *unstable.Node) error {
return errors.New("expected-error")
}
func TestIssue994(t *testing.T) {
var _ unstable.Unmarshaler = (*doc994)(nil)
tomlBytes := []byte(`foo = "bar"`)
var d doc994
err := toml.NewDecoder(bytes.NewReader(tomlBytes)).
EnableUnmarshalerInterface().
Decode(&d)
assert.Error(t, err)
if err.Error() != "expected-error" {
t.Fatalf("expected error 'expected-error', got '%s'", err.Error())
}
}
type doc994ok struct {
S string
}
func (d *doc994ok) UnmarshalTOML(value *unstable.Node) error {
d.S = string(value.Data) + " from unmarshaler"
return nil
}
func TestIssue994_OK(t *testing.T) {
var _ unstable.Unmarshaler = (*doc994ok)(nil)
tomlBytes := []byte(`foo = "bar"`)
var d doc994ok
err := toml.NewDecoder(bytes.NewReader(tomlBytes)).
EnableUnmarshalerInterface().
Decode(&d)
assert.NoError(t, err)
assert.Equal(t, "bar from unmarshaler", d.S)
}