github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/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)
    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)
    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  // Big marshals/unmarshals as a JSON string with 0x prefix.
    94  // The zero value marshals as "0x0".
    95  //
    96  // Negative integers are not supported at this time. Attempting to marshal them will
    97  // return an error. Values larger than 256bits are rejected by Unmarshal but will be
    98  // marshaled without error.
    99  type Big big.Int
   100  
   101  // MarshalText implements encoding.TextMarshaler
   102  func (b Big) MarshalText() ([]byte, error) {
   103  	return []byte(EncodeBig((*big.Int)(&b))), nil
   104  }
   105  
   106  // UnmarshalJSON implements json.Unmarshaler.
   107  func (b *Big) UnmarshalJSON(input []byte) error {
   108  	if !isString(input) {
   109  		return errNonString
   110  	}
   111  	return b.UnmarshalText(input[1 : len(input)-1])
   112  }
   113  
   114  // UnmarshalText implements encoding.TextUnmarshaler
   115  func (b *Big) UnmarshalText(input []byte) error {
   116  	raw, err := checkNumberText(input)
   117  	if err != nil {
   118  		return err
   119  	}
   120  	if len(raw) > 64 {
   121  		return ErrBig256Range
   122  	}
   123  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   124  	end := len(raw)
   125  	for i := range words {
   126  		start := end - bigWordNibbles
   127  		if start < 0 {
   128  			start = 0
   129  		}
   130  		for ri := start; ri < end; ri++ {
   131  			nib := decodeNibble(raw[ri])
   132  			if nib == badNibble {
   133  				return ErrSyntax
   134  			}
   135  			words[i] *= 16
   136  			words[i] += big.Word(nib)
   137  		}
   138  		end = start
   139  	}
   140  	var dec big.Int
   141  	dec.SetBits(words)
   142  	*b = (Big)(dec)
   143  	return nil
   144  }
   145  
   146  // ToInt converts b to a big.Int.
   147  func (b *Big) ToInt() *big.Int {
   148  	return (*big.Int)(b)
   149  }
   150  
   151  // String returns the hex encoding of b.
   152  func (b *Big) String() string {
   153  	return EncodeBig(b.ToInt())
   154  }
   155  
   156  // Uint64 marshals/unmarshals as a JSON string with 0x prefix.
   157  // The zero value marshals as "0x0".
   158  type Uint64 uint64
   159  
   160  // MarshalText implements encoding.TextMarshaler.
   161  func (b Uint64) MarshalText() ([]byte, error) {
   162  	buf := make([]byte, 2, 10)
   163  	copy(buf, `0x`)
   164  	buf = strconv.AppendUint(buf, uint64(b), 16)
   165  	return buf, nil
   166  }
   167  
   168  // UnmarshalJSON implements json.Unmarshaler.
   169  func (b *Uint64) UnmarshalJSON(input []byte) error {
   170  	if !isString(input) {
   171  		return errNonString
   172  	}
   173  	return b.UnmarshalText(input[1 : len(input)-1])
   174  }
   175  
   176  // UnmarshalText implements encoding.TextUnmarshaler
   177  func (b *Uint64) UnmarshalText(input []byte) error {
   178  	raw, err := checkNumberText(input)
   179  	if err != nil {
   180  		return err
   181  	}
   182  	if len(raw) > 16 {
   183  		return ErrUint64Range
   184  	}
   185  	var dec uint64
   186  	for _, byte := range raw {
   187  		nib := decodeNibble(byte)
   188  		if nib == badNibble {
   189  			return ErrSyntax
   190  		}
   191  		dec *= 16
   192  		dec += uint64(nib)
   193  	}
   194  	*b = Uint64(dec)
   195  	return nil
   196  }
   197  
   198  // String returns the hex encoding of b.
   199  func (b Uint64) String() string {
   200  	return EncodeUint64(uint64(b))
   201  }
   202  
   203  // Uint marshals/unmarshals as a JSON string with 0x prefix.
   204  // The zero value marshals as "0x0".
   205  type Uint uint
   206  
   207  // MarshalText implements encoding.TextMarshaler.
   208  func (b Uint) MarshalText() ([]byte, error) {
   209  	return Uint64(b).MarshalText()
   210  }
   211  
   212  // UnmarshalJSON implements json.Unmarshaler.
   213  func (b *Uint) UnmarshalJSON(input []byte) error {
   214  	if !isString(input) {
   215  		return errNonString
   216  	}
   217  	return b.UnmarshalText(input[1 : len(input)-1])
   218  }
   219  
   220  // UnmarshalText implements encoding.TextUnmarshaler.
   221  func (b *Uint) UnmarshalText(input []byte) error {
   222  	var u64 Uint64
   223  	err := u64.UnmarshalText(input)
   224  	if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
   225  		return ErrUintRange
   226  	} else if err != nil {
   227  		return err
   228  	}
   229  	*b = Uint(u64)
   230  	return nil
   231  }
   232  
   233  // String returns the hex encoding of b.
   234  func (b Uint) String() string {
   235  	return EncodeUint64(uint64(b))
   236  }
   237  
   238  func isString(input []byte) bool {
   239  	return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
   240  }
   241  
   242  func bytesHave0xPrefix(input []byte) bool {
   243  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   244  }
   245  
   246  func checkText(input []byte) ([]byte, error) {
   247  	if len(input) == 0 {
   248  		return nil, nil // empty strings are allowed
   249  	}
   250  	if !bytesHave0xPrefix(input) {
   251  		return nil, ErrMissingPrefix
   252  	}
   253  	input = input[2:]
   254  	if len(input)%2 != 0 {
   255  		return nil, ErrOddLength
   256  	}
   257  	return input, nil
   258  }
   259  
   260  func checkNumberText(input []byte) (raw []byte, err error) {
   261  	if len(input) == 0 {
   262  		return nil, nil // empty strings are allowed
   263  	}
   264  	if !bytesHave0xPrefix(input) {
   265  		return nil, ErrMissingPrefix
   266  	}
   267  	input = input[2:]
   268  	if len(input) == 0 {
   269  		return nil, ErrEmptyNumber
   270  	}
   271  	if len(input) > 1 && input[0] == '0' {
   272  		return nil, ErrLeadingZero
   273  	}
   274  	return input, nil
   275  }