Skip to content

Commit 4835627

Browse files
authored
Decode: improve errors on integers and strings (#891)
1 parent cef80b9 commit 4835627

File tree

2 files changed

+70
-4
lines changed

2 files changed

+70
-4
lines changed

unmarshaler.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,12 +149,16 @@ type errorContext struct {
149149
}
150150

151151
func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {
152+
return fmt.Errorf("toml: %s", d.typeMismatchString(toml, target))
153+
}
154+
155+
func (d *decoder) typeMismatchString(toml string, target reflect.Type) string {
152156
if d.errorContext != nil && d.errorContext.Struct != nil {
153157
ctx := d.errorContext
154158
f := ctx.Struct.FieldByIndex(ctx.Field)
155-
return fmt.Errorf("toml: cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)
159+
return fmt.Sprintf("cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)
156160
}
157-
return fmt.Errorf("toml: cannot decode TOML %s into a Go value of type %s", toml, target)
161+
return fmt.Sprintf("cannot decode TOML %s into a Go value of type %s", toml, target)
158162
}
159163

160164
func (d *decoder) expr() *unstable.Node {
@@ -963,7 +967,7 @@ func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error
963967
case reflect.Interface:
964968
r = reflect.ValueOf(i)
965969
default:
966-
return d.typeMismatchError("integer", v.Type())
970+
return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("integer", v.Type()))
967971
}
968972

969973
if !r.Type().AssignableTo(v.Type()) {
@@ -982,7 +986,7 @@ func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error {
982986
case reflect.Interface:
983987
v.Set(reflect.ValueOf(string(value.Data)))
984988
default:
985-
return unstable.NewParserError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind())
989+
return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("string", v.Type()))
986990
}
987991

988992
return nil

unmarshaler_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2048,6 +2048,68 @@ func TestUnmarshalErrors(t *testing.T) {
20482048
require.Equal(t, "toml: cannot decode TOML integer into struct field toml_test.mystruct.Bar of type string", err.Error())
20492049
}
20502050

2051+
func TestUnmarshalStringInvalidStructField(t *testing.T) {
2052+
type Server struct {
2053+
Path string
2054+
Port int
2055+
}
2056+
2057+
type Cfg struct {
2058+
Server Server
2059+
}
2060+
2061+
var cfg Cfg
2062+
2063+
data := `[server]
2064+
path = "/my/path"
2065+
port = "bad"
2066+
`
2067+
2068+
file := strings.NewReader(data)
2069+
err := toml.NewDecoder(file).Decode(&cfg)
2070+
require.Error(t, err)
2071+
2072+
x := err.(*toml.DecodeError)
2073+
require.Equal(t, "toml: cannot decode TOML string into struct field toml_test.Server.Port of type int", x.Error())
2074+
expected := `1| [server]
2075+
2| path = "/my/path"
2076+
3| port = "bad"
2077+
| ~~~~~ cannot decode TOML string into struct field toml_test.Server.Port of type int`
2078+
2079+
require.Equal(t, expected, x.String())
2080+
}
2081+
2082+
func TestUnmarshalIntegerInvalidStructField(t *testing.T) {
2083+
type Server struct {
2084+
Path string
2085+
Port int
2086+
}
2087+
2088+
type Cfg struct {
2089+
Server Server
2090+
}
2091+
2092+
var cfg Cfg
2093+
2094+
data := `[server]
2095+
path = 100
2096+
port = 50
2097+
`
2098+
2099+
file := strings.NewReader(data)
2100+
err := toml.NewDecoder(file).Decode(&cfg)
2101+
require.Error(t, err)
2102+
2103+
x := err.(*toml.DecodeError)
2104+
require.Equal(t, "toml: cannot decode TOML integer into struct field toml_test.Server.Path of type string", x.Error())
2105+
expected := `1| [server]
2106+
2| path = 100
2107+
| ~~~ cannot decode TOML integer into struct field toml_test.Server.Path of type string
2108+
3| port = 50`
2109+
2110+
require.Equal(t, expected, x.String())
2111+
}
2112+
20512113
func TestUnmarshalInvalidTarget(t *testing.T) {
20522114
x := "foo"
20532115
err := toml.Unmarshal([]byte{}, x)

0 commit comments

Comments
 (0)