forked from cerc-io/plugeth
Merge pull request #3722 from fjl/hexutil-text-unmarshal
common/hexutil: implement TextMarshaler, TextUnmarshaler
This commit is contained in:
commit
213b8f9af4
@ -49,6 +49,7 @@ var (
|
|||||||
ErrOddLength = errors.New("hex string has odd length")
|
ErrOddLength = errors.New("hex string has odd length")
|
||||||
ErrUint64Range = errors.New("hex number does not fit into 64 bits")
|
ErrUint64Range = errors.New("hex number does not fit into 64 bits")
|
||||||
ErrUintRange = fmt.Errorf("hex number does not fit into %d bits", uintBits)
|
ErrUintRange = fmt.Errorf("hex number does not fit into %d bits", uintBits)
|
||||||
|
ErrBig256Range = errors.New("hex number does not fit into 256 bits")
|
||||||
)
|
)
|
||||||
|
|
||||||
// Decode decodes a hex string with 0x prefix.
|
// Decode decodes a hex string with 0x prefix.
|
||||||
@ -59,7 +60,11 @@ func Decode(input string) ([]byte, error) {
|
|||||||
if !has0xPrefix(input) {
|
if !has0xPrefix(input) {
|
||||||
return nil, ErrMissingPrefix
|
return nil, ErrMissingPrefix
|
||||||
}
|
}
|
||||||
return hex.DecodeString(input[2:])
|
b, err := hex.DecodeString(input[2:])
|
||||||
|
if err != nil {
|
||||||
|
err = mapError(err)
|
||||||
|
}
|
||||||
|
return b, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
|
// MustDecode decodes a hex string with 0x prefix. It panics for invalid input.
|
||||||
@ -126,11 +131,15 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DecodeBig decodes a hex string with 0x prefix as a quantity.
|
// DecodeBig decodes a hex string with 0x prefix as a quantity.
|
||||||
|
// Numbers larger than 256 bits are not accepted.
|
||||||
func DecodeBig(input string) (*big.Int, error) {
|
func DecodeBig(input string) (*big.Int, error) {
|
||||||
raw, err := checkNumber(input)
|
raw, err := checkNumber(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(raw) > 64 {
|
||||||
|
return nil, ErrBig256Range
|
||||||
|
}
|
||||||
words := make([]big.Word, len(raw)/bigWordNibbles+1)
|
words := make([]big.Word, len(raw)/bigWordNibbles+1)
|
||||||
end := len(raw)
|
end := len(raw)
|
||||||
for i := range words {
|
for i := range words {
|
||||||
@ -169,7 +178,7 @@ func EncodeBig(bigint *big.Int) string {
|
|||||||
if nbits == 0 {
|
if nbits == 0 {
|
||||||
return "0x0"
|
return "0x0"
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("0x%x", bigint)
|
return fmt.Sprintf("%#x", bigint)
|
||||||
}
|
}
|
||||||
|
|
||||||
func has0xPrefix(input string) bool {
|
func has0xPrefix(input string) bool {
|
||||||
|
@ -18,7 +18,6 @@ package hexutil
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -31,7 +30,8 @@ type marshalTest struct {
|
|||||||
type unmarshalTest struct {
|
type unmarshalTest struct {
|
||||||
input string
|
input string
|
||||||
want interface{}
|
want interface{}
|
||||||
wantErr error
|
wantErr error // if set, decoding must fail on any platform
|
||||||
|
wantErr32bit error // if set, decoding must fail on 32bit platforms (used for Uint tests)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -47,6 +47,7 @@ var (
|
|||||||
{referenceBig("ff"), "0xff"},
|
{referenceBig("ff"), "0xff"},
|
||||||
{referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"},
|
{referenceBig("112233445566778899aabbccddeeff"), "0x112233445566778899aabbccddeeff"},
|
||||||
{referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"},
|
{referenceBig("80a7f2c1bcc396c00"), "0x80a7f2c1bcc396c00"},
|
||||||
|
{referenceBig("-80a7f2c1bcc396c00"), "-0x80a7f2c1bcc396c00"},
|
||||||
}
|
}
|
||||||
|
|
||||||
encodeUint64Tests = []marshalTest{
|
encodeUint64Tests = []marshalTest{
|
||||||
@ -56,14 +57,21 @@ var (
|
|||||||
{uint64(0x1122334455667788), "0x1122334455667788"},
|
{uint64(0x1122334455667788), "0x1122334455667788"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
encodeUintTests = []marshalTest{
|
||||||
|
{uint(0), "0x0"},
|
||||||
|
{uint(1), "0x1"},
|
||||||
|
{uint(0xff), "0xff"},
|
||||||
|
{uint(0x11223344), "0x11223344"},
|
||||||
|
}
|
||||||
|
|
||||||
decodeBytesTests = []unmarshalTest{
|
decodeBytesTests = []unmarshalTest{
|
||||||
// invalid
|
// invalid
|
||||||
{input: ``, wantErr: ErrEmptyString},
|
{input: ``, wantErr: ErrEmptyString},
|
||||||
{input: `0`, wantErr: ErrMissingPrefix},
|
{input: `0`, wantErr: ErrMissingPrefix},
|
||||||
{input: `0x0`, wantErr: hex.ErrLength},
|
{input: `0x0`, wantErr: ErrOddLength},
|
||||||
{input: `0x023`, wantErr: hex.ErrLength},
|
{input: `0x023`, wantErr: ErrOddLength},
|
||||||
{input: `0xxx`, wantErr: hex.InvalidByteError('x')},
|
{input: `0xxx`, wantErr: ErrSyntax},
|
||||||
{input: `0x01zz01`, wantErr: hex.InvalidByteError('z')},
|
{input: `0x01zz01`, wantErr: ErrSyntax},
|
||||||
// valid
|
// valid
|
||||||
{input: `0x`, want: []byte{}},
|
{input: `0x`, want: []byte{}},
|
||||||
{input: `0X`, want: []byte{}},
|
{input: `0X`, want: []byte{}},
|
||||||
@ -83,6 +91,10 @@ var (
|
|||||||
{input: `0x01`, wantErr: ErrLeadingZero},
|
{input: `0x01`, wantErr: ErrLeadingZero},
|
||||||
{input: `0xx`, wantErr: ErrSyntax},
|
{input: `0xx`, wantErr: ErrSyntax},
|
||||||
{input: `0x1zz01`, wantErr: ErrSyntax},
|
{input: `0x1zz01`, wantErr: ErrSyntax},
|
||||||
|
{
|
||||||
|
input: `0x10000000000000000000000000000000000000000000000000000000000000000`,
|
||||||
|
wantErr: ErrBig256Range,
|
||||||
|
},
|
||||||
// valid
|
// valid
|
||||||
{input: `0x0`, want: big.NewInt(0)},
|
{input: `0x0`, want: big.NewInt(0)},
|
||||||
{input: `0x2`, want: big.NewInt(0x2)},
|
{input: `0x2`, want: big.NewInt(0x2)},
|
||||||
@ -99,6 +111,10 @@ var (
|
|||||||
input: `0xffffffffffffffffffffffffffffffffffff`,
|
input: `0xffffffffffffffffffffffffffffffffffff`,
|
||||||
want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
|
want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: `0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff`,
|
||||||
|
want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
decodeUint64Tests = []unmarshalTest{
|
decodeUint64Tests = []unmarshalTest{
|
||||||
|
@ -25,28 +25,33 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
jsonNull = []byte("null")
|
textZero = []byte(`0x0`)
|
||||||
jsonZero = []byte(`"0x0"`)
|
|
||||||
errNonString = errors.New("cannot unmarshal non-string as hex data")
|
errNonString = errors.New("cannot unmarshal non-string as hex data")
|
||||||
errNegativeBigInt = errors.New("hexutil.Big: can't marshal negative integer")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
|
// Bytes marshals/unmarshals as a JSON string with 0x prefix.
|
||||||
// The empty slice marshals as "0x".
|
// The empty slice marshals as "0x".
|
||||||
type Bytes []byte
|
type Bytes []byte
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
// MarshalText implements encoding.TextMarshaler
|
||||||
func (b Bytes) MarshalJSON() ([]byte, error) {
|
func (b Bytes) MarshalText() ([]byte, error) {
|
||||||
result := make([]byte, len(b)*2+4)
|
result := make([]byte, len(b)*2+2)
|
||||||
copy(result, `"0x`)
|
copy(result, `0x`)
|
||||||
hex.Encode(result[3:], b)
|
hex.Encode(result[2:], b)
|
||||||
result[len(result)-1] = '"'
|
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
func (b *Bytes) UnmarshalJSON(input []byte) error {
|
func (b *Bytes) UnmarshalJSON(input []byte) error {
|
||||||
raw, err := checkJSON(input)
|
if !isString(input) {
|
||||||
|
return errNonString
|
||||||
|
}
|
||||||
|
return b.UnmarshalText(input[1 : len(input)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (b *Bytes) UnmarshalText(input []byte) error {
|
||||||
|
raw, err := checkText(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -64,17 +69,11 @@ func (b Bytes) String() string {
|
|||||||
return Encode(b)
|
return Encode(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON decodes input as a JSON string with 0x prefix. The length of out
|
// 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
|
// determines the required input length. This function is commonly used to implement the
|
||||||
// UnmarshalJSON method for fixed-size types:
|
// UnmarshalText method for fixed-size types.
|
||||||
//
|
func UnmarshalFixedText(typname string, input, out []byte) error {
|
||||||
// type Foo [8]byte
|
raw, err := checkText(input)
|
||||||
//
|
|
||||||
// func (f *Foo) UnmarshalJSON(input []byte) error {
|
|
||||||
// return hexutil.UnmarshalJSON("Foo", input, f[:])
|
|
||||||
// }
|
|
||||||
func UnmarshalJSON(typname string, input, out []byte) error {
|
|
||||||
raw, err := checkJSON(input)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -91,34 +90,36 @@ func UnmarshalJSON(typname string, input, out []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Big marshals/unmarshals as a JSON string with 0x prefix. The zero value marshals as
|
// Big marshals/unmarshals as a JSON string with 0x prefix.
|
||||||
// "0x0". Negative integers are not supported at this time. Attempting to marshal them
|
// The zero value marshals as "0x0".
|
||||||
// will return an error.
|
//
|
||||||
|
// Negative integers are not supported at this time. Attempting to marshal them will
|
||||||
|
// return an error. Values larger than 256bits are rejected by Unmarshal but will be
|
||||||
|
// marshaled without error.
|
||||||
type Big big.Int
|
type Big big.Int
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
// MarshalText implements encoding.TextMarshaler
|
||||||
func (b *Big) MarshalJSON() ([]byte, error) {
|
func (b Big) MarshalText() ([]byte, error) {
|
||||||
if b == nil {
|
return []byte(EncodeBig((*big.Int)(&b))), nil
|
||||||
return jsonNull, nil
|
|
||||||
}
|
|
||||||
bigint := (*big.Int)(b)
|
|
||||||
if bigint.Sign() == -1 {
|
|
||||||
return nil, errNegativeBigInt
|
|
||||||
}
|
|
||||||
nbits := bigint.BitLen()
|
|
||||||
if nbits == 0 {
|
|
||||||
return jsonZero, nil
|
|
||||||
}
|
|
||||||
enc := fmt.Sprintf(`"0x%x"`, bigint)
|
|
||||||
return []byte(enc), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
func (b *Big) UnmarshalJSON(input []byte) error {
|
func (b *Big) UnmarshalJSON(input []byte) error {
|
||||||
raw, err := checkNumberJSON(input)
|
if !isString(input) {
|
||||||
|
return errNonString
|
||||||
|
}
|
||||||
|
return b.UnmarshalText(input[1 : len(input)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler
|
||||||
|
func (b *Big) UnmarshalText(input []byte) error {
|
||||||
|
raw, err := checkNumberText(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(raw) > 64 {
|
||||||
|
return ErrBig256Range
|
||||||
|
}
|
||||||
words := make([]big.Word, len(raw)/bigWordNibbles+1)
|
words := make([]big.Word, len(raw)/bigWordNibbles+1)
|
||||||
end := len(raw)
|
end := len(raw)
|
||||||
for i := range words {
|
for i := range words {
|
||||||
@ -156,18 +157,25 @@ func (b *Big) String() string {
|
|||||||
// The zero value marshals as "0x0".
|
// The zero value marshals as "0x0".
|
||||||
type Uint64 uint64
|
type Uint64 uint64
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (b Uint64) MarshalJSON() ([]byte, error) {
|
func (b Uint64) MarshalText() ([]byte, error) {
|
||||||
buf := make([]byte, 3, 12)
|
buf := make([]byte, 2, 10)
|
||||||
copy(buf, `"0x`)
|
copy(buf, `0x`)
|
||||||
buf = strconv.AppendUint(buf, uint64(b), 16)
|
buf = strconv.AppendUint(buf, uint64(b), 16)
|
||||||
buf = append(buf, '"')
|
|
||||||
return buf, nil
|
return buf, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
func (b *Uint64) UnmarshalJSON(input []byte) error {
|
func (b *Uint64) UnmarshalJSON(input []byte) error {
|
||||||
raw, err := checkNumberJSON(input)
|
if !isString(input) {
|
||||||
|
return errNonString
|
||||||
|
}
|
||||||
|
return b.UnmarshalText(input[1 : len(input)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler
|
||||||
|
func (b *Uint64) UnmarshalText(input []byte) error {
|
||||||
|
raw, err := checkNumberText(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -196,19 +204,27 @@ func (b Uint64) String() string {
|
|||||||
// The zero value marshals as "0x0".
|
// The zero value marshals as "0x0".
|
||||||
type Uint uint
|
type Uint uint
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler.
|
// MarshalText implements encoding.TextMarshaler.
|
||||||
func (b Uint) MarshalJSON() ([]byte, error) {
|
func (b Uint) MarshalText() ([]byte, error) {
|
||||||
return Uint64(b).MarshalJSON()
|
return Uint64(b).MarshalText()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler.
|
// UnmarshalJSON implements json.Unmarshaler.
|
||||||
func (b *Uint) UnmarshalJSON(input []byte) error {
|
func (b *Uint) UnmarshalJSON(input []byte) error {
|
||||||
|
if !isString(input) {
|
||||||
|
return errNonString
|
||||||
|
}
|
||||||
|
return b.UnmarshalText(input[1 : len(input)-1])
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
|
func (b *Uint) UnmarshalText(input []byte) error {
|
||||||
var u64 Uint64
|
var u64 Uint64
|
||||||
err := u64.UnmarshalJSON(input)
|
err := u64.UnmarshalText(input)
|
||||||
if err != nil {
|
if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
|
||||||
return err
|
|
||||||
} else if u64 > Uint64(^uint(0)) {
|
|
||||||
return ErrUintRange
|
return ErrUintRange
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
*b = Uint(u64)
|
*b = Uint(u64)
|
||||||
return nil
|
return nil
|
||||||
@ -227,28 +243,21 @@ func bytesHave0xPrefix(input []byte) bool {
|
|||||||
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
|
return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkJSON(input []byte) (raw []byte, err error) {
|
func checkText(input []byte) ([]byte, error) {
|
||||||
if !isString(input) {
|
if len(input) == 0 {
|
||||||
return nil, errNonString
|
|
||||||
}
|
|
||||||
if len(input) == 2 {
|
|
||||||
return nil, nil // empty strings are allowed
|
return nil, nil // empty strings are allowed
|
||||||
}
|
}
|
||||||
if !bytesHave0xPrefix(input[1:]) {
|
if !bytesHave0xPrefix(input) {
|
||||||
return nil, ErrMissingPrefix
|
return nil, ErrMissingPrefix
|
||||||
}
|
}
|
||||||
input = input[3 : len(input)-1]
|
input = input[2:]
|
||||||
if len(input)%2 != 0 {
|
if len(input)%2 != 0 {
|
||||||
return nil, ErrOddLength
|
return nil, ErrOddLength
|
||||||
}
|
}
|
||||||
return input, nil
|
return input, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkNumberJSON(input []byte) (raw []byte, err error) {
|
func checkNumberText(input []byte) (raw []byte, err error) {
|
||||||
if !isString(input) {
|
|
||||||
return nil, errNonString
|
|
||||||
}
|
|
||||||
input = input[1 : len(input)-1]
|
|
||||||
if len(input) == 0 {
|
if len(input) == 0 {
|
||||||
return nil, nil // empty strings are allowed
|
return nil, nil // empty strings are allowed
|
||||||
}
|
}
|
||||||
|
45
common/hexutil/json_example_test.go
Normal file
45
common/hexutil/json_example_test.go
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
// Copyright 2017 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package hexutil_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MyType [5]byte
|
||||||
|
|
||||||
|
func (v *MyType) UnmarshalText(input []byte) error {
|
||||||
|
return hexutil.UnmarshalFixedText("MyType", input, v[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v MyType) String() string {
|
||||||
|
return hexutil.Bytes(v[:]).String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ExampleUnmarshalFixedText() {
|
||||||
|
var v1, v2 MyType
|
||||||
|
fmt.Println("v1 error:", json.Unmarshal([]byte(`"0x01"`), &v1))
|
||||||
|
fmt.Println("v2 error:", json.Unmarshal([]byte(`"0x0101010101"`), &v2))
|
||||||
|
fmt.Println("v2:", v2)
|
||||||
|
// Output:
|
||||||
|
// v1 error: hex string has length 2, want 10 for MyType
|
||||||
|
// v2 error: <nil>
|
||||||
|
// v2: 0x0101010101
|
||||||
|
}
|
@ -19,6 +19,8 @@ package hexutil
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"math/big"
|
"math/big"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@ -55,9 +57,11 @@ func referenceBytes(s string) []byte {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var errJSONEOF = errors.New("unexpected end of JSON input")
|
||||||
|
|
||||||
var unmarshalBytesTests = []unmarshalTest{
|
var unmarshalBytesTests = []unmarshalTest{
|
||||||
// invalid encoding
|
// invalid encoding
|
||||||
{input: "", wantErr: errNonString},
|
{input: "", wantErr: errJSONEOF},
|
||||||
{input: "null", wantErr: errNonString},
|
{input: "null", wantErr: errNonString},
|
||||||
{input: "10", wantErr: errNonString},
|
{input: "10", wantErr: errNonString},
|
||||||
{input: `"0"`, wantErr: ErrMissingPrefix},
|
{input: `"0"`, wantErr: ErrMissingPrefix},
|
||||||
@ -80,7 +84,7 @@ var unmarshalBytesTests = []unmarshalTest{
|
|||||||
func TestUnmarshalBytes(t *testing.T) {
|
func TestUnmarshalBytes(t *testing.T) {
|
||||||
for _, test := range unmarshalBytesTests {
|
for _, test := range unmarshalBytesTests {
|
||||||
var v Bytes
|
var v Bytes
|
||||||
err := v.UnmarshalJSON([]byte(test.input))
|
err := json.Unmarshal([]byte(test.input), &v)
|
||||||
if !checkError(t, test.input, err, test.wantErr) {
|
if !checkError(t, test.input, err, test.wantErr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -104,7 +108,7 @@ func BenchmarkUnmarshalBytes(b *testing.B) {
|
|||||||
func TestMarshalBytes(t *testing.T) {
|
func TestMarshalBytes(t *testing.T) {
|
||||||
for _, test := range encodeBytesTests {
|
for _, test := range encodeBytesTests {
|
||||||
in := test.input.([]byte)
|
in := test.input.([]byte)
|
||||||
out, err := Bytes(in).MarshalJSON()
|
out, err := json.Marshal(Bytes(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%x: %v", in, err)
|
t.Errorf("%x: %v", in, err)
|
||||||
continue
|
continue
|
||||||
@ -122,7 +126,7 @@ func TestMarshalBytes(t *testing.T) {
|
|||||||
|
|
||||||
var unmarshalBigTests = []unmarshalTest{
|
var unmarshalBigTests = []unmarshalTest{
|
||||||
// invalid encoding
|
// invalid encoding
|
||||||
{input: "", wantErr: errNonString},
|
{input: "", wantErr: errJSONEOF},
|
||||||
{input: "null", wantErr: errNonString},
|
{input: "null", wantErr: errNonString},
|
||||||
{input: "10", wantErr: errNonString},
|
{input: "10", wantErr: errNonString},
|
||||||
{input: `"0"`, wantErr: ErrMissingPrefix},
|
{input: `"0"`, wantErr: ErrMissingPrefix},
|
||||||
@ -130,6 +134,10 @@ var unmarshalBigTests = []unmarshalTest{
|
|||||||
{input: `"0x01"`, wantErr: ErrLeadingZero},
|
{input: `"0x01"`, wantErr: ErrLeadingZero},
|
||||||
{input: `"0xx"`, wantErr: ErrSyntax},
|
{input: `"0xx"`, wantErr: ErrSyntax},
|
||||||
{input: `"0x1zz01"`, wantErr: ErrSyntax},
|
{input: `"0x1zz01"`, wantErr: ErrSyntax},
|
||||||
|
{
|
||||||
|
input: `"0x10000000000000000000000000000000000000000000000000000000000000000"`,
|
||||||
|
wantErr: ErrBig256Range,
|
||||||
|
},
|
||||||
|
|
||||||
// valid encoding
|
// valid encoding
|
||||||
{input: `""`, want: big.NewInt(0)},
|
{input: `""`, want: big.NewInt(0)},
|
||||||
@ -148,12 +156,16 @@ var unmarshalBigTests = []unmarshalTest{
|
|||||||
input: `"0xffffffffffffffffffffffffffffffffffff"`,
|
input: `"0xffffffffffffffffffffffffffffffffffff"`,
|
||||||
want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
|
want: referenceBig("ffffffffffffffffffffffffffffffffffff"),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
input: `"0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"`,
|
||||||
|
want: referenceBig("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnmarshalBig(t *testing.T) {
|
func TestUnmarshalBig(t *testing.T) {
|
||||||
for _, test := range unmarshalBigTests {
|
for _, test := range unmarshalBigTests {
|
||||||
var v Big
|
var v Big
|
||||||
err := v.UnmarshalJSON([]byte(test.input))
|
err := json.Unmarshal([]byte(test.input), &v)
|
||||||
if !checkError(t, test.input, err, test.wantErr) {
|
if !checkError(t, test.input, err, test.wantErr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -177,7 +189,7 @@ func BenchmarkUnmarshalBig(b *testing.B) {
|
|||||||
func TestMarshalBig(t *testing.T) {
|
func TestMarshalBig(t *testing.T) {
|
||||||
for _, test := range encodeBigTests {
|
for _, test := range encodeBigTests {
|
||||||
in := test.input.(*big.Int)
|
in := test.input.(*big.Int)
|
||||||
out, err := (*Big)(in).MarshalJSON()
|
out, err := json.Marshal((*Big)(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%d: %v", in, err)
|
t.Errorf("%d: %v", in, err)
|
||||||
continue
|
continue
|
||||||
@ -195,7 +207,7 @@ func TestMarshalBig(t *testing.T) {
|
|||||||
|
|
||||||
var unmarshalUint64Tests = []unmarshalTest{
|
var unmarshalUint64Tests = []unmarshalTest{
|
||||||
// invalid encoding
|
// invalid encoding
|
||||||
{input: "", wantErr: errNonString},
|
{input: "", wantErr: errJSONEOF},
|
||||||
{input: "null", wantErr: errNonString},
|
{input: "null", wantErr: errNonString},
|
||||||
{input: "10", wantErr: errNonString},
|
{input: "10", wantErr: errNonString},
|
||||||
{input: `"0"`, wantErr: ErrMissingPrefix},
|
{input: `"0"`, wantErr: ErrMissingPrefix},
|
||||||
@ -219,7 +231,7 @@ var unmarshalUint64Tests = []unmarshalTest{
|
|||||||
func TestUnmarshalUint64(t *testing.T) {
|
func TestUnmarshalUint64(t *testing.T) {
|
||||||
for _, test := range unmarshalUint64Tests {
|
for _, test := range unmarshalUint64Tests {
|
||||||
var v Uint64
|
var v Uint64
|
||||||
err := v.UnmarshalJSON([]byte(test.input))
|
err := json.Unmarshal([]byte(test.input), &v)
|
||||||
if !checkError(t, test.input, err, test.wantErr) {
|
if !checkError(t, test.input, err, test.wantErr) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -241,7 +253,7 @@ func BenchmarkUnmarshalUint64(b *testing.B) {
|
|||||||
func TestMarshalUint64(t *testing.T) {
|
func TestMarshalUint64(t *testing.T) {
|
||||||
for _, test := range encodeUint64Tests {
|
for _, test := range encodeUint64Tests {
|
||||||
in := test.input.(uint64)
|
in := test.input.(uint64)
|
||||||
out, err := Uint64(in).MarshalJSON()
|
out, err := json.Marshal(Uint64(in))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%d: %v", in, err)
|
t.Errorf("%d: %v", in, err)
|
||||||
continue
|
continue
|
||||||
@ -256,3 +268,72 @@ func TestMarshalUint64(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMarshalUint(t *testing.T) {
|
||||||
|
for _, test := range encodeUintTests {
|
||||||
|
in := test.input.(uint)
|
||||||
|
out, err := json.Marshal(Uint(in))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("%d: %v", in, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if want := `"` + test.want + `"`; string(out) != want {
|
||||||
|
t.Errorf("%d: MarshalJSON output mismatch: got %q, want %q", in, out, want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if out := (Uint)(in).String(); out != test.want {
|
||||||
|
t.Errorf("%x: String mismatch: got %q, want %q", in, out, test.want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// These are variables (not constants) to avoid constant overflow
|
||||||
|
// checks in the compiler on 32bit platforms.
|
||||||
|
maxUint33bits = uint64(^uint32(0)) + 1
|
||||||
|
maxUint64bits = ^uint64(0)
|
||||||
|
)
|
||||||
|
|
||||||
|
var unmarshalUintTests = []unmarshalTest{
|
||||||
|
// invalid encoding
|
||||||
|
{input: "", wantErr: errJSONEOF},
|
||||||
|
{input: "null", wantErr: errNonString},
|
||||||
|
{input: "10", wantErr: errNonString},
|
||||||
|
{input: `"0"`, wantErr: ErrMissingPrefix},
|
||||||
|
{input: `"0x"`, wantErr: ErrEmptyNumber},
|
||||||
|
{input: `"0x01"`, wantErr: ErrLeadingZero},
|
||||||
|
{input: `"0x100000000"`, want: uint(maxUint33bits), wantErr32bit: ErrUintRange},
|
||||||
|
{input: `"0xfffffffffffffffff"`, wantErr: ErrUintRange},
|
||||||
|
{input: `"0xx"`, wantErr: ErrSyntax},
|
||||||
|
{input: `"0x1zz01"`, wantErr: ErrSyntax},
|
||||||
|
|
||||||
|
// valid encoding
|
||||||
|
{input: `""`, want: uint(0)},
|
||||||
|
{input: `"0x0"`, want: uint(0)},
|
||||||
|
{input: `"0x2"`, want: uint(0x2)},
|
||||||
|
{input: `"0x2F2"`, want: uint(0x2f2)},
|
||||||
|
{input: `"0X2F2"`, want: uint(0x2f2)},
|
||||||
|
{input: `"0x1122aaff"`, want: uint(0x1122aaff)},
|
||||||
|
{input: `"0xbbb"`, want: uint(0xbbb)},
|
||||||
|
{input: `"0xffffffff"`, want: uint(0xffffffff)},
|
||||||
|
{input: `"0xffffffffffffffff"`, want: uint(maxUint64bits), wantErr32bit: ErrUintRange},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnmarshalUint(t *testing.T) {
|
||||||
|
for _, test := range unmarshalUintTests {
|
||||||
|
var v Uint
|
||||||
|
err := json.Unmarshal([]byte(test.input), &v)
|
||||||
|
if uintBits == 32 && test.wantErr32bit != nil {
|
||||||
|
checkError(t, test.input, err, test.wantErr32bit)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !checkError(t, test.input, err, test.wantErr) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if uint(v) != test.want.(uint) {
|
||||||
|
t.Errorf("input %s: value mismatch: got %d, want %d", test.input, v, test.want)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -71,14 +71,14 @@ func (h Hash) Format(s fmt.State, c rune) {
|
|||||||
fmt.Fprintf(s, "%"+string(c), h[:])
|
fmt.Fprintf(s, "%"+string(c), h[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON parses a hash in its hex from to a hash.
|
// UnmarshalText parses a hash in hex syntax.
|
||||||
func (h *Hash) UnmarshalJSON(input []byte) error {
|
func (h *Hash) UnmarshalText(input []byte) error {
|
||||||
return hexutil.UnmarshalJSON("Hash", input, h[:])
|
return hexutil.UnmarshalFixedText("Hash", input, h[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize given hash to JSON
|
// MarshalText returns the hex representation of h.
|
||||||
func (h Hash) MarshalJSON() ([]byte, error) {
|
func (h Hash) MarshalText() ([]byte, error) {
|
||||||
return hexutil.Bytes(h[:]).MarshalJSON()
|
return hexutil.Bytes(h[:]).MarshalText()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets the hash to the value of b. If b is larger than len(h) it will panic
|
// Sets the hash to the value of b. If b is larger than len(h) it will panic
|
||||||
@ -171,14 +171,14 @@ func (a *Address) Set(other Address) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Serialize given address to JSON
|
// MarshalText returns the hex representation of a.
|
||||||
func (a Address) MarshalJSON() ([]byte, error) {
|
func (a Address) MarshalText() ([]byte, error) {
|
||||||
return hexutil.Bytes(a[:]).MarshalJSON()
|
return hexutil.Bytes(a[:]).MarshalText()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse address from raw json data
|
// UnmarshalText parses a hash in hex syntax.
|
||||||
func (a *Address) UnmarshalJSON(input []byte) error {
|
func (a *Address) UnmarshalText(input []byte) error {
|
||||||
return hexutil.UnmarshalJSON("Address", input, a[:])
|
return hexutil.UnmarshalFixedText("Address", input, a[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// PP Pretty Prints a byte slice in the following format:
|
// PP Pretty Prints a byte slice in the following format:
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"math/big"
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -37,7 +38,6 @@ func TestBytesConversion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestHashJsonValidation(t *testing.T) {
|
func TestHashJsonValidation(t *testing.T) {
|
||||||
var h Hash
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
Prefix string
|
Prefix string
|
||||||
Size int
|
Size int
|
||||||
@ -52,7 +52,8 @@ func TestHashJsonValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
input := `"` + test.Prefix + strings.Repeat("0", test.Size) + `"`
|
input := `"` + test.Prefix + strings.Repeat("0", test.Size) + `"`
|
||||||
err := h.UnmarshalJSON([]byte(input))
|
var v Hash
|
||||||
|
err := json.Unmarshal([]byte(input), &v)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if test.Error != "" {
|
if test.Error != "" {
|
||||||
t.Errorf("%s: error mismatch: have nil, want %q", input, test.Error)
|
t.Errorf("%s: error mismatch: have nil, want %q", input, test.Error)
|
||||||
@ -66,7 +67,6 @@ func TestHashJsonValidation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestAddressUnmarshalJSON(t *testing.T) {
|
func TestAddressUnmarshalJSON(t *testing.T) {
|
||||||
var a Address
|
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
Input string
|
Input string
|
||||||
ShouldErr bool
|
ShouldErr bool
|
||||||
@ -81,7 +81,8 @@ func TestAddressUnmarshalJSON(t *testing.T) {
|
|||||||
{`"0x0000000000000000000000000000000000000010"`, false, big.NewInt(16)},
|
{`"0x0000000000000000000000000000000000000010"`, false, big.NewInt(16)},
|
||||||
}
|
}
|
||||||
for i, test := range tests {
|
for i, test := range tests {
|
||||||
err := a.UnmarshalJSON([]byte(test.Input))
|
var v Address
|
||||||
|
err := json.Unmarshal([]byte(test.Input), &v)
|
||||||
if err != nil && !test.ShouldErr {
|
if err != nil && !test.ShouldErr {
|
||||||
t.Errorf("test #%d: unexpected error: %v", i, err)
|
t.Errorf("test #%d: unexpected error: %v", i, err)
|
||||||
}
|
}
|
||||||
@ -89,8 +90,8 @@ func TestAddressUnmarshalJSON(t *testing.T) {
|
|||||||
if test.ShouldErr {
|
if test.ShouldErr {
|
||||||
t.Errorf("test #%d: expected error, got none", i)
|
t.Errorf("test #%d: expected error, got none", i)
|
||||||
}
|
}
|
||||||
if a.Big().Cmp(test.Output) != 0 {
|
if v.Big().Cmp(test.Output) != 0 {
|
||||||
t.Errorf("test #%d: address mismatch: have %v, want %v", i, a.Big(), test.Output)
|
t.Errorf("test #%d: address mismatch: have %v, want %v", i, v.Big(), test.Output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,14 +62,14 @@ func (n BlockNonce) Uint64() uint64 {
|
|||||||
return binary.BigEndian.Uint64(n[:])
|
return binary.BigEndian.Uint64(n[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler
|
// MarshalText encodes n as a hex string with 0x prefix.
|
||||||
func (n BlockNonce) MarshalJSON() ([]byte, error) {
|
func (n BlockNonce) MarshalText() ([]byte, error) {
|
||||||
return hexutil.Bytes(n[:]).MarshalJSON()
|
return hexutil.Bytes(n[:]).MarshalText()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON implements json.Unmarshaler
|
// UnmarshalText implements encoding.TextUnmarshaler.
|
||||||
func (n *BlockNonce) UnmarshalJSON(input []byte) error {
|
func (n *BlockNonce) UnmarshalText(input []byte) error {
|
||||||
return hexutil.UnmarshalJSON("BlockNonce", input, n[:])
|
return hexutil.UnmarshalFixedText("BlockNonce", input, n[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Header represents a block header in the Ethereum blockchain.
|
// Header represents a block header in the Ethereum blockchain.
|
||||||
|
@ -75,14 +75,14 @@ func (b Bloom) TestBytes(test []byte) bool {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON encodes b as a hex string with 0x prefix.
|
// MarshalText encodes b as a hex string with 0x prefix.
|
||||||
func (b Bloom) MarshalJSON() ([]byte, error) {
|
func (b Bloom) MarshalText() ([]byte, error) {
|
||||||
return hexutil.Bytes(b[:]).MarshalJSON()
|
return hexutil.Bytes(b[:]).MarshalText()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON b as a hex string with 0x prefix.
|
// UnmarshalText b as a hex string with 0x prefix.
|
||||||
func (b *Bloom) UnmarshalJSON(input []byte) error {
|
func (b *Bloom) UnmarshalText(input []byte) error {
|
||||||
return hexutil.UnmarshalJSON("Bloom", input, b[:])
|
return hexutil.UnmarshalFixedText("Bloom", input, b[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func CreateBloom(receipts Receipts) Bloom {
|
func CreateBloom(receipts Receipts) Bloom {
|
||||||
|
Loading…
Reference in New Issue
Block a user