github.com/neatlab/neatio@v1.7.3-0.20220425043230-d903e92fcc75/utilities/common/hexutil/json.go (about)

     1  package hexutil
     2  
     3  import (
     4  	"encoding/hex"
     5  	"encoding/json"
     6  	"fmt"
     7  	"math/big"
     8  	"reflect"
     9  	"strconv"
    10  )
    11  
    12  var (
    13  	bytesT  = reflect.TypeOf(Bytes(nil))
    14  	bigT    = reflect.TypeOf((*Big)(nil))
    15  	uintT   = reflect.TypeOf(Uint(0))
    16  	uint64T = reflect.TypeOf(Uint64(0))
    17  )
    18  
    19  type Bytes []byte
    20  
    21  func (b Bytes) MarshalText() ([]byte, error) {
    22  	result := make([]byte, len(b)*2+2)
    23  	copy(result, `0x`)
    24  	hex.Encode(result[2:], b)
    25  	return result, nil
    26  }
    27  
    28  func (b *Bytes) UnmarshalJSON(input []byte) error {
    29  	if !isString(input) {
    30  		return errNonString(bytesT)
    31  	}
    32  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
    33  }
    34  
    35  func (b *Bytes) UnmarshalText(input []byte) error {
    36  	raw, err := checkText(input, true)
    37  	if err != nil {
    38  		return err
    39  	}
    40  	dec := make([]byte, len(raw)/2)
    41  	if _, err = hex.Decode(dec, raw); err != nil {
    42  		err = mapError(err)
    43  	} else {
    44  		*b = dec
    45  	}
    46  	return err
    47  }
    48  
    49  func (b Bytes) String() string {
    50  	return Encode(b)
    51  }
    52  
    53  func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
    54  	if !isString(input) {
    55  		return errNonString(typ)
    56  	}
    57  	return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
    58  }
    59  
    60  func UnmarshalFixedText(typname string, input, out []byte) error {
    61  	raw, err := checkText(input, true)
    62  	if err != nil {
    63  		return err
    64  	}
    65  	if len(raw)/2 != len(out) {
    66  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
    67  	}
    68  
    69  	for _, b := range raw {
    70  		if decodeNibble(b) == badNibble {
    71  			return ErrSyntax
    72  		}
    73  	}
    74  	hex.Decode(out, raw)
    75  
    76  	return nil
    77  }
    78  
    79  func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
    80  	raw, err := checkText(input, false)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	if len(raw)/2 != len(out) {
    85  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
    86  	}
    87  
    88  	for _, b := range raw {
    89  		if decodeNibble(b) == badNibble {
    90  			return ErrSyntax
    91  		}
    92  	}
    93  	hex.Decode(out, raw)
    94  	return nil
    95  }
    96  
    97  type Big big.Int
    98  
    99  func (b Big) MarshalText() ([]byte, error) {
   100  	return []byte(EncodeBig((*big.Int)(&b))), nil
   101  }
   102  
   103  func (b *Big) UnmarshalJSON(input []byte) error {
   104  	if !isString(input) {
   105  		return errNonString(bigT)
   106  	}
   107  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT)
   108  }
   109  
   110  func (b *Big) UnmarshalText(input []byte) error {
   111  	raw, err := checkNumberText(input)
   112  	if err != nil {
   113  		return err
   114  	}
   115  	if len(raw) > 64 {
   116  		return ErrBig256Range
   117  	}
   118  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   119  	end := len(raw)
   120  	for i := range words {
   121  		start := end - bigWordNibbles
   122  		if start < 0 {
   123  			start = 0
   124  		}
   125  		for ri := start; ri < end; ri++ {
   126  			nib := decodeNibble(raw[ri])
   127  			if nib == badNibble {
   128  				return ErrSyntax
   129  			}
   130  			words[i] *= 16
   131  			words[i] += big.Word(nib)
   132  		}
   133  		end = start
   134  	}
   135  	var dec big.Int
   136  	dec.SetBits(words)
   137  	*b = (Big)(dec)
   138  	return nil
   139  }
   140  
   141  func (b *Big) ToInt() *big.Int {
   142  	return (*big.Int)(b)
   143  }
   144  
   145  func (b *Big) String() string {
   146  	return EncodeBig(b.ToInt())
   147  }
   148  
   149  type Uint64 uint64
   150  
   151  func (b Uint64) MarshalText() ([]byte, error) {
   152  	buf := make([]byte, 2, 10)
   153  	copy(buf, `0x`)
   154  	buf = strconv.AppendUint(buf, uint64(b), 16)
   155  	return buf, nil
   156  }
   157  
   158  func (b *Uint64) UnmarshalJSON(input []byte) error {
   159  	if !isString(input) {
   160  		return errNonString(uint64T)
   161  	}
   162  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T)
   163  }
   164  
   165  func (b *Uint64) UnmarshalText(input []byte) error {
   166  	raw, err := checkNumberText(input)
   167  	if err != nil {
   168  		return err
   169  	}
   170  	if len(raw) > 16 {
   171  		return ErrUint64Range
   172  	}
   173  	var dec uint64
   174  	for _, byte := range raw {
   175  		nib := decodeNibble(byte)
   176  		if nib == badNibble {
   177  			return ErrSyntax
   178  		}
   179  		dec *= 16
   180  		dec += nib
   181  	}
   182  	*b = Uint64(dec)
   183  	return nil
   184  }
   185  
   186  func (b Uint64) String() string {
   187  	return EncodeUint64(uint64(b))
   188  }
   189  
   190  type Uint uint
   191  
   192  func (b Uint) MarshalText() ([]byte, error) {
   193  	return Uint64(b).MarshalText()
   194  }
   195  
   196  func (b *Uint) UnmarshalJSON(input []byte) error {
   197  	if !isString(input) {
   198  		return errNonString(uintT)
   199  	}
   200  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT)
   201  }
   202  
   203  func (b *Uint) UnmarshalText(input []byte) error {
   204  	var u64 Uint64
   205  	err := u64.UnmarshalText(input)
   206  	if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
   207  		return ErrUintRange
   208  	} else if err != nil {
   209  		return err
   210  	}
   211  	*b = Uint(u64)
   212  	return nil
   213  }
   214  
   215  func (b Uint) String() string {
   216  	return EncodeUint64(uint64(b))
   217  }
   218  
   219  func isString(input []byte) bool {
   220  	return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
   221  }
   222  
   223  func bytesHave0xPrefix(input []byte) bool {
   224  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   225  }
   226  
   227  func checkText(input []byte, wantPrefix bool) ([]byte, error) {
   228  	if len(input) == 0 {
   229  		return nil, nil
   230  	}
   231  	if bytesHave0xPrefix(input) {
   232  		input = input[2:]
   233  	} else if wantPrefix {
   234  		return nil, ErrMissingPrefix
   235  	}
   236  	if len(input)%2 != 0 {
   237  		return nil, ErrOddLength
   238  	}
   239  	return input, nil
   240  }
   241  
   242  func checkNumberText(input []byte) (raw []byte, err error) {
   243  	if len(input) == 0 {
   244  		return nil, nil
   245  	}
   246  	if !bytesHave0xPrefix(input) {
   247  		return nil, ErrMissingPrefix
   248  	}
   249  	input = input[2:]
   250  	if len(input) == 0 {
   251  		return nil, ErrEmptyNumber
   252  	}
   253  	if len(input) > 1 && input[0] == '0' {
   254  		return nil, ErrLeadingZero
   255  	}
   256  	return input, nil
   257  }
   258  
   259  func wrapTypeError(err error, typ reflect.Type) error {
   260  	if _, ok := err.(*decError); ok {
   261  		return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
   262  	}
   263  	return err
   264  }
   265  
   266  func errNonString(typ reflect.Type) error {
   267  	return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
   268  }