github.com/theQRL/go-zond@v0.2.1/common/hexutil/json.go (about)

     1  // Copyright 2016 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package hexutil
    18  
    19  import (
    20  	"encoding/hex"
    21  	"encoding/json"
    22  	"fmt"
    23  	"math/big"
    24  	"reflect"
    25  	"strconv"
    26  )
    27  
    28  var (
    29  	bytesT  = reflect.TypeOf(Bytes(nil))
    30  	byteszT = reflect.TypeOf(BytesZ(nil))
    31  	bigT    = reflect.TypeOf((*Big)(nil))
    32  	uintT   = reflect.TypeOf(Uint(0))
    33  	uint64T = reflect.TypeOf(Uint64(0))
    34  )
    35  
    36  // Bytes marshals/unmarshals as a JSON string with 0x prefix.
    37  // The empty slice marshals as "0x".
    38  type Bytes []byte
    39  
    40  // MarshalText implements encoding.TextMarshaler
    41  func (b Bytes) MarshalText() ([]byte, error) {
    42  	result := make([]byte, len(b)*2+2)
    43  	copy(result, `0x`)
    44  	hex.Encode(result[2:], b)
    45  	return result, nil
    46  }
    47  
    48  // UnmarshalJSON implements json.Unmarshaler.
    49  func (b *Bytes) UnmarshalJSON(input []byte) error {
    50  	if !isString(input) {
    51  		return errNonString(bytesT)
    52  	}
    53  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
    54  }
    55  
    56  // UnmarshalText implements encoding.TextUnmarshaler.
    57  func (b *Bytes) UnmarshalText(input []byte) error {
    58  	raw, err := checkText(input, true)
    59  	if err != nil {
    60  		return err
    61  	}
    62  	dec := make([]byte, len(raw)/2)
    63  	if _, err = hex.Decode(dec, raw); err != nil {
    64  		err = mapError(err)
    65  	} else {
    66  		*b = dec
    67  	}
    68  	return err
    69  }
    70  
    71  // String returns the hex encoding of b.
    72  func (b Bytes) String() string {
    73  	return Encode(b)
    74  }
    75  
    76  // ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type.
    77  func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" }
    78  
    79  // UnmarshalGraphQL unmarshals the provided GraphQL query data.
    80  func (b *Bytes) UnmarshalGraphQL(input interface{}) error {
    81  	var err error
    82  	switch input := input.(type) {
    83  	case string:
    84  		data, err := Decode(input)
    85  		if err != nil {
    86  			return err
    87  		}
    88  		*b = data
    89  	default:
    90  		err = fmt.Errorf("unexpected type %T for Bytes", input)
    91  	}
    92  	return err
    93  }
    94  
    95  // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out
    96  // determines the required input length. This function is commonly used to implement the
    97  // UnmarshalJSON method for fixed-size types.
    98  func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
    99  	if !isString(input) {
   100  		return errNonString(typ)
   101  	}
   102  	return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
   103  }
   104  
   105  func UnmarshalFixedJSONZ(typ reflect.Type, input, out []byte) error {
   106  	if !isString(input) {
   107  		return errNonString(typ)
   108  	}
   109  	return wrapTypeError(UnmarshalFixedTextZ(typ.String(), input[1:len(input)-1], out), typ)
   110  }
   111  
   112  // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out
   113  // determines the required input length. This function is commonly used to implement the
   114  // UnmarshalText method for fixed-size types.
   115  func UnmarshalFixedText(typname string, input, out []byte) error {
   116  	raw, err := checkText(input, true)
   117  	if err != nil {
   118  		return err
   119  	}
   120  	if len(raw)/2 != len(out) {
   121  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
   122  	}
   123  	// Pre-verify syntax before modifying out.
   124  	for _, b := range raw {
   125  		if decodeNibble(b) == badNibble {
   126  			return ErrSyntax
   127  		}
   128  	}
   129  	hex.Decode(out, raw)
   130  	return nil
   131  }
   132  
   133  func UnmarshalFixedTextZ(typname string, input, out []byte) error {
   134  	raw, err := checkTextZ(input, true)
   135  	if err != nil {
   136  		return err
   137  	}
   138  	if len(raw)/2 != len(out) {
   139  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
   140  	}
   141  	// Pre-verify syntax before modifying out.
   142  	for _, b := range raw {
   143  		if decodeNibble(b) == badNibble {
   144  			return ErrSyntax
   145  		}
   146  	}
   147  	hex.Decode(out, raw)
   148  	return nil
   149  }
   150  
   151  // UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The
   152  // length of out determines the required input length. This function is commonly used to
   153  // implement the UnmarshalText method for fixed-size types.
   154  func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
   155  	raw, err := checkText(input, false)
   156  	if err != nil {
   157  		return err
   158  	}
   159  	if len(raw)/2 != len(out) {
   160  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
   161  	}
   162  	// Pre-verify syntax before modifying out.
   163  	for _, b := range raw {
   164  		if decodeNibble(b) == badNibble {
   165  			return ErrSyntax
   166  		}
   167  	}
   168  	hex.Decode(out, raw)
   169  	return nil
   170  }
   171  
   172  // Big marshals/unmarshals as a JSON string with 0x prefix.
   173  // The zero value marshals as "0x0".
   174  //
   175  // Negative integers are not supported at this time. Attempting to marshal them will
   176  // return an error. Values larger than 256bits are rejected by Unmarshal but will be
   177  // marshaled without error.
   178  type Big big.Int
   179  
   180  // MarshalText implements encoding.TextMarshaler
   181  func (b Big) MarshalText() ([]byte, error) {
   182  	return []byte(EncodeBig((*big.Int)(&b))), nil
   183  }
   184  
   185  // UnmarshalJSON implements json.Unmarshaler.
   186  func (b *Big) UnmarshalJSON(input []byte) error {
   187  	if !isString(input) {
   188  		return errNonString(bigT)
   189  	}
   190  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT)
   191  }
   192  
   193  // UnmarshalText implements encoding.TextUnmarshaler
   194  func (b *Big) UnmarshalText(input []byte) error {
   195  	raw, err := checkNumberText(input)
   196  	if err != nil {
   197  		return err
   198  	}
   199  	if len(raw) > 64 {
   200  		return ErrBig256Range
   201  	}
   202  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   203  	end := len(raw)
   204  	for i := range words {
   205  		start := end - bigWordNibbles
   206  		if start < 0 {
   207  			start = 0
   208  		}
   209  		for ri := start; ri < end; ri++ {
   210  			nib := decodeNibble(raw[ri])
   211  			if nib == badNibble {
   212  				return ErrSyntax
   213  			}
   214  			words[i] *= 16
   215  			words[i] += big.Word(nib)
   216  		}
   217  		end = start
   218  	}
   219  	var dec big.Int
   220  	dec.SetBits(words)
   221  	*b = (Big)(dec)
   222  	return nil
   223  }
   224  
   225  // ToInt converts b to a big.Int.
   226  func (b *Big) ToInt() *big.Int {
   227  	return (*big.Int)(b)
   228  }
   229  
   230  // String returns the hex encoding of b.
   231  func (b *Big) String() string {
   232  	return EncodeBig(b.ToInt())
   233  }
   234  
   235  // ImplementsGraphQLType returns true if Big implements the provided GraphQL type.
   236  func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" }
   237  
   238  // UnmarshalGraphQL unmarshals the provided GraphQL query data.
   239  func (b *Big) UnmarshalGraphQL(input interface{}) error {
   240  	var err error
   241  	switch input := input.(type) {
   242  	case string:
   243  		return b.UnmarshalText([]byte(input))
   244  	case int32:
   245  		var num big.Int
   246  		num.SetInt64(int64(input))
   247  		*b = Big(num)
   248  	default:
   249  		err = fmt.Errorf("unexpected type %T for BigInt", input)
   250  	}
   251  	return err
   252  }
   253  
   254  // Uint64 marshals/unmarshals as a JSON string with 0x prefix.
   255  // The zero value marshals as "0x0".
   256  type Uint64 uint64
   257  
   258  // MarshalText implements encoding.TextMarshaler.
   259  func (b Uint64) MarshalText() ([]byte, error) {
   260  	buf := make([]byte, 2, 10)
   261  	copy(buf, `0x`)
   262  	buf = strconv.AppendUint(buf, uint64(b), 16)
   263  	return buf, nil
   264  }
   265  
   266  // UnmarshalJSON implements json.Unmarshaler.
   267  func (b *Uint64) UnmarshalJSON(input []byte) error {
   268  	if !isString(input) {
   269  		return errNonString(uint64T)
   270  	}
   271  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T)
   272  }
   273  
   274  // UnmarshalText implements encoding.TextUnmarshaler
   275  func (b *Uint64) UnmarshalText(input []byte) error {
   276  	raw, err := checkNumberText(input)
   277  	if err != nil {
   278  		return err
   279  	}
   280  	if len(raw) > 16 {
   281  		return ErrUint64Range
   282  	}
   283  	var dec uint64
   284  	for _, byte := range raw {
   285  		nib := decodeNibble(byte)
   286  		if nib == badNibble {
   287  			return ErrSyntax
   288  		}
   289  		dec *= 16
   290  		dec += nib
   291  	}
   292  	*b = Uint64(dec)
   293  	return nil
   294  }
   295  
   296  // String returns the hex encoding of b.
   297  func (b Uint64) String() string {
   298  	return EncodeUint64(uint64(b))
   299  }
   300  
   301  // ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type.
   302  func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" }
   303  
   304  // UnmarshalGraphQL unmarshals the provided GraphQL query data.
   305  func (b *Uint64) UnmarshalGraphQL(input interface{}) error {
   306  	var err error
   307  	switch input := input.(type) {
   308  	case string:
   309  		return b.UnmarshalText([]byte(input))
   310  	case int32:
   311  		*b = Uint64(input)
   312  	default:
   313  		err = fmt.Errorf("unexpected type %T for Long", input)
   314  	}
   315  	return err
   316  }
   317  
   318  // Uint marshals/unmarshals as a JSON string with 0x prefix.
   319  // The zero value marshals as "0x0".
   320  type Uint uint
   321  
   322  // MarshalText implements encoding.TextMarshaler.
   323  func (b Uint) MarshalText() ([]byte, error) {
   324  	return Uint64(b).MarshalText()
   325  }
   326  
   327  // UnmarshalJSON implements json.Unmarshaler.
   328  func (b *Uint) UnmarshalJSON(input []byte) error {
   329  	if !isString(input) {
   330  		return errNonString(uintT)
   331  	}
   332  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT)
   333  }
   334  
   335  // UnmarshalText implements encoding.TextUnmarshaler.
   336  func (b *Uint) UnmarshalText(input []byte) error {
   337  	var u64 Uint64
   338  	err := u64.UnmarshalText(input)
   339  	if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
   340  		return ErrUintRange
   341  	} else if err != nil {
   342  		return err
   343  	}
   344  	*b = Uint(u64)
   345  	return nil
   346  }
   347  
   348  // String returns the hex encoding of b.
   349  func (b Uint) String() string {
   350  	return EncodeUint64(uint64(b))
   351  }
   352  
   353  // BytesZ marshals/unmarshals as a JSON string with Z prefix.
   354  // The empty slice marshals as "Z".
   355  type BytesZ []byte
   356  
   357  // MarshalText implements encoding.TextMarshaler
   358  func (b BytesZ) MarshalText() ([]byte, error) {
   359  	result := make([]byte, len(b)*2+1)
   360  	copy(result, PrefixZ)
   361  	hex.Encode(result[1:], b)
   362  	return result, nil
   363  }
   364  
   365  // UnmarshalJSON implements json.Unmarshaler.
   366  func (b *BytesZ) UnmarshalJSON(input []byte) error {
   367  	if !isString(input) {
   368  		return errNonString(byteszT)
   369  	}
   370  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
   371  }
   372  
   373  // UnmarshalText implements encoding.TextUnmarshaler.
   374  func (b *BytesZ) UnmarshalText(input []byte) error {
   375  	raw, err := checkTextZ(input, true)
   376  	if err != nil {
   377  		return err
   378  	}
   379  	dec := make([]byte, len(raw)/2)
   380  	if _, err = hex.Decode(dec, raw); err != nil {
   381  		err = mapError(err)
   382  	} else {
   383  		*b = dec
   384  	}
   385  	return err
   386  }
   387  
   388  // String returns the hex encoding of b.
   389  func (b BytesZ) String() string {
   390  	return EncodeZ(b)
   391  }
   392  
   393  // ImplementsGraphQLType returns true if BytesZ implements the specified GraphQL type.
   394  func (b BytesZ) ImplementsGraphQLType(name string) bool { return name == "BytesZ" }
   395  
   396  // UnmarshalGraphQL unmarshals the provided GraphQL query data.
   397  func (b *BytesZ) UnmarshalGraphQL(input interface{}) error {
   398  	var err error
   399  	switch input := input.(type) {
   400  	case string:
   401  		data, err := DecodeZ(input)
   402  		if err != nil {
   403  			return err
   404  		}
   405  		*b = data
   406  	default:
   407  		err = fmt.Errorf("unexpected type %T for BytesZ", input)
   408  	}
   409  	return err
   410  }
   411  
   412  func isString(input []byte) bool {
   413  	return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
   414  }
   415  
   416  func bytesHave0xPrefix(input []byte) bool {
   417  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   418  }
   419  
   420  func bytesHaveZPrefix(input []byte) bool {
   421  	return len(input) >= 1 && input[0] == 'Z'
   422  }
   423  
   424  func checkText(input []byte, wantPrefix bool) ([]byte, error) {
   425  	if len(input) == 0 {
   426  		return nil, nil // empty strings are allowed
   427  	}
   428  	if bytesHave0xPrefix(input) {
   429  		input = input[2:]
   430  	} else if wantPrefix {
   431  		return nil, ErrMissingPrefix
   432  	}
   433  	if len(input)%2 != 0 {
   434  		return nil, ErrOddLength
   435  	}
   436  	return input, nil
   437  }
   438  
   439  func checkTextZ(input []byte, wantPrefix bool) ([]byte, error) {
   440  	if len(input) == 0 {
   441  		return nil, nil // empty strings are allowed
   442  	}
   443  	if bytesHaveZPrefix(input) {
   444  		input = input[1:]
   445  	} else if wantPrefix {
   446  		return nil, ErrMissingPrefixZ
   447  	}
   448  	if len(input)%2 != 0 {
   449  		return nil, ErrOddLength
   450  	}
   451  	return input, nil
   452  }
   453  
   454  func checkNumberText(input []byte) (raw []byte, err error) {
   455  	if len(input) == 0 {
   456  		return nil, nil // empty strings are allowed
   457  	}
   458  	if !bytesHave0xPrefix(input) {
   459  		return nil, ErrMissingPrefix
   460  	}
   461  	input = input[2:]
   462  	if len(input) == 0 {
   463  		return nil, ErrEmptyNumber
   464  	}
   465  	if len(input) > 1 && input[0] == '0' {
   466  		return nil, ErrLeadingZero
   467  	}
   468  	return input, nil
   469  }
   470  
   471  func wrapTypeError(err error, typ reflect.Type) error {
   472  	if _, ok := err.(*decError); ok {
   473  		return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
   474  	}
   475  	return err
   476  }
   477  
   478  func errNonString(typ reflect.Type) error {
   479  	return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
   480  }