Decode: improve errors on integers and strings (#891)
This commit is contained in:
+8
-4
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user