github.com/ylsGit/go-ethereum@v1.6.5/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  	"errors"
    22  	"fmt"
    23  	"math/big"
    24  	"strconv"
    25  )
    26  
    27  var (
    28  	textZero     = []byte(`0x0`)
    29  	errNonString = errors.New("cannot unmarshal non-string as hex data")
    30  )
    31  
    32  // Bytes marshals/unmarshals as a JSON string with 0x prefix.
    33  // The empty slice marshals as "0x".
    34  type Bytes []byte
    35  
    36  // MarshalText implements encoding.TextMarshaler
    37  func (b Bytes) MarshalText() ([]byte, error) {
    38  	result := make([]byte, len(b)*2+2)
    39  	copy(result, `0x`)
    40  	hex.Encode(result[2:], b)
    41  	return result, nil
    42  }
    43  
    44  // UnmarshalJSON implements json.Unmarshaler.
    45  func (b *Bytes) UnmarshalJSON(input []byte) error {
    46  	if !isString(input) {
    47  		return errNonString
    48  	}
    49  	return b.UnmarshalText(input[1 : len(input)-1])
    50  }
    51  
    52  // UnmarshalText implements encoding.TextUnmarshaler.
    53  func (b *Bytes) UnmarshalText(input []byte) error {
    54  	raw, err := checkText(input, true)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	dec := make([]byte, len(raw)/2)
    59  	if _, err = hex.Decode(dec, raw); err != nil {
    60  		err = mapError(err)
    61  	} else {
    62  		*b = dec
    63  	}
    64  	return err
    65  }
    66  
    67  // String returns the hex encoding of b.
    68  func (b Bytes) String() string {
    69  	return Encode(b)
    70  }
    71  
    72  // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out
    73  // determines the required input length. This function is commonly used to implement the
    74  // UnmarshalText method for fixed-size types.
    75  func UnmarshalFixedText(typname string, input, out []byte) error {
    76  	raw, err := checkText(input, true)
    77  	if err != nil {
    78  		return err
    79  	}
    80  	if len(raw)/2 != len(out) {
    81  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
    82  	}
    83  	// Pre-verify syntax before modifying out.
    84  	for _, b := range raw {
    85  		if decodeNibble(b) == badNibble {
    86  			return ErrSyntax
    87  		}
    88  	}
    89  	hex.Decode(out, raw)
    90  	return nil
    91  }
    92  
    93  // UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The
    94  // length of out determines the required input length. This function is commonly used to
    95  // implement the UnmarshalText method for fixed-size types.
    96  func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
    97  	raw, err := checkText(input, false)
    98  	if err != nil {
    99  		return err
   100  	}
   101  	if len(raw)/2 != len(out) {
   102  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
   103  	}
   104  	// Pre-verify syntax before modifying out.
   105  	for _, b := range raw {
   106  		if decodeNibble(b) == badNibble {
   107  			return ErrSyntax
   108  		}
   109  	}
   110  	hex.Decode(out, raw)
   111  	return nil
   112  }
   113  
   114  // Big marshals/unmarshals as a JSON string with 0x prefix.
   115  // The zero value marshals as "0x0".
   116  //
   117  // Negative integers are not supported at this time. Attempting to marshal them will
   118  // return an error. Values larger than 256bits are rejected by Unmarshal but will be
   119  // marshaled without error.
   120  type Big big.Int
   121  
   122  // MarshalText implements encoding.TextMarshaler
   123  func (b Big) MarshalText() ([]byte, error) {
   124  	return []byte(EncodeBig((*big.Int)(&b))), nil
   125  }
   126  
   127  // UnmarshalJSON implements json.Unmarshaler.
   128  func (b *Big) UnmarshalJSON(input []byte) error {
   129  	if !isString(input) {
   130  		return errNonString
   131  	}
   132  	return b.UnmarshalText(input[1 : len(input)-1])
   133  }
   134  
   135  // UnmarshalText implements encoding.TextUnmarshaler
   136  func (b *Big) UnmarshalText(input []byte) error {
   137  	raw, err := checkNumberText(input)
   138  	if err != nil {
   139  		return err
   140  	}
   141  	if len(raw) > 64 {
   142  		return ErrBig256Range
   143  	}
   144  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   145  	end := len(raw)
   146  	for i := range words {
   147  		start := end - bigWordNibbles
   148  		if start < 0 {
   149  			start = 0
   150  		}
   151  		for ri := start; ri < end; ri++ {
   152  			nib := decodeNibble(raw[ri])
   153  			if nib == badNibble {
   154  				return ErrSyntax
   155  			}
   156  			words[i] *= 16
   157  			words[i] += big.Word(nib)
   158  		}
   159  		end = start
   160  	}
   161  	var dec big.Int
   162  	dec.SetBits(words)
   163  	*b = (Big)(dec)
   164  	return nil
   165  }
   166  
   167  // ToInt converts b to a big.Int.
   168  func (b *Big) ToInt() *big.Int {
   169  	return (*big.Int)(b)
   170  }
   171  
   172  // String returns the hex encoding of b.
   173  func (b *Big) String() string {
   174  	return EncodeBig(b.ToInt())
   175  }
   176  
   177  // Uint64 marshals/unmarshals as a JSON string with 0x prefix.
   178  // The zero value marshals as "0x0".
   179  type Uint64 uint64
   180  
   181  // MarshalText implements encoding.TextMarshaler.
   182  func (b Uint64) MarshalText() ([]byte, error) {
   183  	buf := make([]byte, 2, 10)
   184  	copy(buf, `0x`)
   185  	buf = strconv.AppendUint(buf, uint64(b), 16)
   186  	return buf, nil
   187  }
   188  
   189  // UnmarshalJSON implements json.Unmarshaler.
   190  func (b *Uint64) UnmarshalJSON(input []byte) error {
   191  	if !isString(input) {
   192  		return errNonString
   193  	}
   194  	return b.UnmarshalText(input[1 : len(input)-1])
   195  }
   196  
   197  // UnmarshalText implements encoding.TextUnmarshaler
   198  func (b *Uint64) UnmarshalText(input []byte) error {
   199  	raw, err := checkNumberText(input)
   200  	if err != nil {
   201  		return err
   202  	}
   203  	if len(raw) > 16 {
   204  		return ErrUint64Range
   205  	}
   206  	var dec uint64
   207  	for _, byte := range raw {
   208  		nib := decodeNibble(byte)
   209  		if nib == badNibble {
   210  			return ErrSyntax
   211  		}
   212  		dec *= 16
   213  		dec += uint64(nib)
   214  	}
   215  	*b = Uint64(dec)
   216  	return nil
   217  }
   218  
   219  // String returns the hex encoding of b.
   220  func (b Uint64) String() string {
   221  	return EncodeUint64(uint64(b))
   222  }
   223  
   224  // Uint marshals/unmarshals as a JSON string with 0x prefix.
   225  // The zero value marshals as "0x0".
   226  type Uint uint
   227  
   228  // MarshalText implements encoding.TextMarshaler.
   229  func (b Uint) MarshalText() ([]byte, error) {
   230  	return Uint64(b).MarshalText()
   231  }
   232  
   233  // UnmarshalJSON implements json.Unmarshaler.
   234  func (b *Uint) UnmarshalJSON(input []byte) error {
   235  	if !isString(input) {
   236  		return errNonString
   237  	}
   238  	return b.UnmarshalText(input[1 : len(input)-1])
   239  }
   240  
   241  // UnmarshalText implements encoding.TextUnmarshaler.
   242  func (b *Uint) UnmarshalText(input []byte) error {
   243  	var u64 Uint64
   244  	err := u64.UnmarshalText(input)
   245  	if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
   246  		return ErrUintRange
   247  	} else if err != nil {
   248  		return err
   249  	}
   250  	*b = Uint(u64)
   251  	return nil
   252  }
   253  
   254  // String returns the hex encoding of b.
   255  func (b Uint) String() string {
   256  	return EncodeUint64(uint64(b))
   257  }
   258  
   259  func isString(input []byte) bool {
   260  	return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
   261  }
   262  
   263  func bytesHave0xPrefix(input []byte) bool {
   264  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   265  }
   266  
   267  func checkText(input []byte, wantPrefix bool) ([]byte, error) {
   268  	if len(input) == 0 {
   269  		return nil, nil // empty strings are allowed
   270  	}
   271  	if bytesHave0xPrefix(input) {
   272  		input = input[2:]
   273  	} else if wantPrefix {
   274  		return nil, ErrMissingPrefix
   275  	}
   276  	if len(input)%2 != 0 {
   277  		return nil, ErrOddLength
   278  	}
   279  	return input, nil
   280  }
   281  
   282  func checkNumberText(input []byte) (raw []byte, err error) {
   283  	if len(input) == 0 {
   284  		return nil, nil // empty strings are allowed
   285  	}
   286  	if !bytesHave0xPrefix(input) {
   287  		return nil, ErrMissingPrefix
   288  	}
   289  	input = input[2:]
   290  	if len(input) == 0 {
   291  		return nil, ErrEmptyNumber
   292  	}
   293  	if len(input) > 1 && input[0] == '0' {
   294  		return nil, ErrLeadingZero
   295  	}
   296  	return input, nil
   297  }