Decode: improve errors on integers and strings (#891)

This commit is contained in:
Thomas Pelletier
2023-08-28 11:17:48 -04:00
committed by GitHub
parent cef80b96a4
commit 4835627845
2 changed files with 70 additions and 4 deletions
+8 -4
View File
@@ -149,12 +149,16 @@ type errorContext struct {
} }
func (d *decoder) typeMismatchError(toml string, target reflect.Type) error { func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {
return fmt.Errorf("toml: %s", d.typeMismatchString(toml, target))
}
func (d *decoder) typeMismatchString(toml string, target reflect.Type) string {
if d.errorContext != nil && d.errorContext.Struct != nil { if d.errorContext != nil && d.errorContext.Struct != nil {
ctx := d.errorContext ctx := d.errorContext
f := ctx.Struct.FieldByIndex(ctx.Field) f := ctx.Struct.FieldByIndex(ctx.Field)
return fmt.Errorf("toml: cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type) return fmt.Sprintf("cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)
} }
return fmt.Errorf("toml: cannot decode TOML %s into a Go value of type %s", toml, target) return fmt.Sprintf("cannot decode TOML %s into a Go value of type %s", toml, target)
} }
func (d *decoder) expr() *unstable.Node { func (d *decoder) expr() *unstable.Node {
@@ -963,7 +967,7 @@ func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error
case reflect.Interface: case reflect.Interface:
r = reflect.ValueOf(i) r = reflect.ValueOf(i)
default: default:
return d.typeMismatchError("integer", v.Type()) return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("integer", v.Type()))
} }
if !r.Type().AssignableTo(v.Type()) { if !r.Type().AssignableTo(v.Type()) {
@@ -982,7 +986,7 @@ func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error {
case reflect.Interface: case reflect.Interface:
v.Set(reflect.ValueOf(string(value.Data))) v.Set(reflect.ValueOf(string(value.Data)))
default: default:
return unstable.NewParserError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind()) return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("string", v.Type()))
} }
return nil return nil
+62
View File
@@ -2048,6 +2048,68 @@ func TestUnmarshalErrors(t *testing.T) {
require.Equal(t, "toml: cannot decode TOML integer into struct field toml_test.mystruct.Bar of type string", err.Error()) require.Equal(t, "toml: cannot decode TOML integer into struct field toml_test.mystruct.Bar of type string", err.Error())
} }
func TestUnmarshalStringInvalidStructField(t *testing.T) {
type Server struct {
Path string
Port int
}
type Cfg struct {
Server Server
}
var cfg Cfg
data := `[server]
path = "/my/path"
port = "bad"
`
file := strings.NewReader(data)
err := toml.NewDecoder(file).Decode(&cfg)
require.Error(t, err)
x := err.(*toml.DecodeError)
require.Equal(t, "toml: cannot decode TOML string into struct field toml_test.Server.Port of type int", x.Error())
expected := `1| [server]
2| path = "/my/path"
3| port = "bad"
| ~~~~~ cannot decode TOML string into struct field toml_test.Server.Port of type int`
require.Equal(t, expected, x.String())
}
func TestUnmarshalIntegerInvalidStructField(t *testing.T) {
type Server struct {
Path string
Port int
}
type Cfg struct {
Server Server
}
var cfg Cfg
data := `[server]
path = 100
port = 50
`
file := strings.NewReader(data)
err := toml.NewDecoder(file).Decode(&cfg)
require.Error(t, err)
x := err.(*toml.DecodeError)
require.Equal(t, "toml: cannot decode TOML integer into struct field toml_test.Server.Path of type string", x.Error())
expected := `1| [server]
2| path = 100
| ~~~ cannot decode TOML integer into struct field toml_test.Server.Path of type string
3| port = 50`
require.Equal(t, expected, x.String())
}
func TestUnmarshalInvalidTarget(t *testing.T) { func TestUnmarshalInvalidTarget(t *testing.T) {
x := "foo" x := "foo"
err := toml.Unmarshal([]byte{}, x) err := toml.Unmarshal([]byte{}, x)