diff options
author | Felix Lange <fjl@twurst.com> | 2017-06-23 16:50:49 +0800 |
---|---|---|
committer | Felix Lange <fjl@twurst.com> | 2017-06-27 19:15:12 +0800 |
commit | 4a741df757cf6b1d1b4c0e8c875c34b650f46167 (patch) | |
tree | 057d995a3847f9f983a4dcdf41cf3bc9fb9b82a2 /common/hexutil/json.go | |
parent | b664bedcf21f30b54af542e0b4ba4e24c01968fd (diff) | |
download | dexon-4a741df757cf6b1d1b4c0e8c875c34b650f46167.tar dexon-4a741df757cf6b1d1b4c0e8c875c34b650f46167.tar.gz dexon-4a741df757cf6b1d1b4c0e8c875c34b650f46167.tar.bz2 dexon-4a741df757cf6b1d1b4c0e8c875c34b650f46167.tar.lz dexon-4a741df757cf6b1d1b4c0e8c875c34b650f46167.tar.xz dexon-4a741df757cf6b1d1b4c0e8c875c34b650f46167.tar.zst dexon-4a741df757cf6b1d1b4c0e8c875c34b650f46167.zip |
common/hexutil: wrap errors in json.UnmarshalTypeError
This adds type and struct field context to error messages.
Instead of "hex string of odd length" users will now see "json: cannot
unmarshal hex string of odd length into Go struct field SendTxArgs.from
of type common.Address".
Diffstat (limited to 'common/hexutil/json.go')
-rw-r--r-- | common/hexutil/json.go | 47 |
1 files changed, 36 insertions, 11 deletions
diff --git a/common/hexutil/json.go b/common/hexutil/json.go index 1bc1d014c..943288fad 100644 --- a/common/hexutil/json.go +++ b/common/hexutil/json.go @@ -18,15 +18,19 @@ package hexutil import ( "encoding/hex" - "errors" + "encoding/json" "fmt" "math/big" + "reflect" "strconv" ) var ( - textZero = []byte(`0x0`) - errNonString = errors.New("cannot unmarshal non-string as hex data") + textZero = []byte(`0x0`) + bytesT = reflect.TypeOf(Bytes(nil)) + bigT = reflect.TypeOf((*Big)(nil)) + uintT = reflect.TypeOf(Uint(0)) + uint64T = reflect.TypeOf(Uint64(0)) ) // Bytes marshals/unmarshals as a JSON string with 0x prefix. @@ -44,9 +48,9 @@ func (b Bytes) MarshalText() ([]byte, error) { // UnmarshalJSON implements json.Unmarshaler. func (b *Bytes) UnmarshalJSON(input []byte) error { if !isString(input) { - return errNonString + return errNonString(bytesT) } - return b.UnmarshalText(input[1 : len(input)-1]) + return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT) } // UnmarshalText implements encoding.TextUnmarshaler. @@ -69,6 +73,16 @@ func (b Bytes) String() string { return Encode(b) } +// UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out +// determines the required input length. This function is commonly used to implement the +// UnmarshalJSON method for fixed-size types. +func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error { + if !isString(input) { + return errNonString(typ) + } + return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ) +} + // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out // determines the required input length. This function is commonly used to implement the // UnmarshalText method for fixed-size types. @@ -127,9 +141,9 @@ func (b Big) MarshalText() ([]byte, error) { // UnmarshalJSON implements json.Unmarshaler. func (b *Big) UnmarshalJSON(input []byte) error { if !isString(input) { - return errNonString + return errNonString(bigT) } - return b.UnmarshalText(input[1 : len(input)-1]) + return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT) } // UnmarshalText implements encoding.TextUnmarshaler @@ -189,9 +203,9 @@ func (b Uint64) MarshalText() ([]byte, error) { // UnmarshalJSON implements json.Unmarshaler. func (b *Uint64) UnmarshalJSON(input []byte) error { if !isString(input) { - return errNonString + return errNonString(uint64T) } - return b.UnmarshalText(input[1 : len(input)-1]) + return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T) } // UnmarshalText implements encoding.TextUnmarshaler @@ -233,9 +247,9 @@ func (b Uint) MarshalText() ([]byte, error) { // UnmarshalJSON implements json.Unmarshaler. func (b *Uint) UnmarshalJSON(input []byte) error { if !isString(input) { - return errNonString + return errNonString(uintT) } - return b.UnmarshalText(input[1 : len(input)-1]) + return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT) } // UnmarshalText implements encoding.TextUnmarshaler. @@ -295,3 +309,14 @@ func checkNumberText(input []byte) (raw []byte, err error) { } return input, nil } + +func wrapTypeError(err error, typ reflect.Type) error { + if _, ok := err.(*decError); ok { + return &json.UnmarshalTypeError{Value: err.Error(), Type: typ} + } + return err +} + +func errNonString(typ reflect.Type) error { + return &json.UnmarshalTypeError{Value: "non-string", Type: typ} +} |