github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/common/hexutil/json.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:34</date>
    10  //</624450073622745088>
    11  
    12  
    13  package hexutil
    14  
    15  import (
    16  	"encoding/hex"
    17  	"encoding/json"
    18  	"fmt"
    19  	"math/big"
    20  	"reflect"
    21  	"strconv"
    22  )
    23  
    24  var (
    25  	bytesT  = reflect.TypeOf(Bytes(nil))
    26  	bigT    = reflect.TypeOf((*Big)(nil))
    27  	uintT   = reflect.TypeOf(Uint(0))
    28  	uint64T = reflect.TypeOf(Uint64(0))
    29  )
    30  
    31  //字节封送/取消封送为带0x前缀的JSON字符串。
    32  //空切片封送为“0x”。
    33  type Bytes []byte
    34  
    35  //MarshalText实现Encoding.TextMarshaler
    36  func (b Bytes) MarshalText() ([]byte, error) {
    37  	result := make([]byte, len(b)*2+2)
    38  	copy(result, `0x`)
    39  	hex.Encode(result[2:], b)
    40  	return result, nil
    41  }
    42  
    43  //unmashaljson实现json.unmasheler。
    44  func (b *Bytes) UnmarshalJSON(input []byte) error {
    45  	if !isString(input) {
    46  		return errNonString(bytesT)
    47  	}
    48  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT)
    49  }
    50  
    51  //UnmarshalText实现encoding.textUnmarshaller。
    52  func (b *Bytes) UnmarshalText(input []byte) error {
    53  	raw, err := checkText(input, true)
    54  	if err != nil {
    55  		return err
    56  	}
    57  	dec := make([]byte, len(raw)/2)
    58  	if _, err = hex.Decode(dec, raw); err != nil {
    59  		err = mapError(err)
    60  	} else {
    61  		*b = dec
    62  	}
    63  	return err
    64  }
    65  
    66  //字符串返回b的十六进制编码。
    67  func (b Bytes) String() string {
    68  	return Encode(b)
    69  }
    70  
    71  //unmarshalfixedjson将输入解码为带0x前缀的字符串。输出长度
    72  //确定所需的输入长度。此函数通常用于实现
    73  //固定大小类型的unmashaljson方法。
    74  func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error {
    75  	if !isString(input) {
    76  		return errNonString(typ)
    77  	}
    78  	return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ)
    79  }
    80  
    81  //unmarshalfixedtext将输入解码为带0x前缀的字符串。输出长度
    82  //确定所需的输入长度。此函数通常用于实现
    83  //为固定大小类型取消标记文本方法。
    84  func UnmarshalFixedText(typname string, input, out []byte) error {
    85  	raw, err := checkText(input, true)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	if len(raw)/2 != len(out) {
    90  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
    91  	}
    92  //在修改out之前预先验证语法。
    93  	for _, b := range raw {
    94  		if decodeNibble(b) == badNibble {
    95  			return ErrSyntax
    96  		}
    97  	}
    98  	hex.Decode(out, raw)
    99  	return nil
   100  }
   101  
   102  //unmarshalfixedUnprefixedText将输入解码为带可选0x前缀的字符串。这个
   103  //输出长度决定所需的输入长度。此函数通常用于
   104  //为固定大小类型实现UnmarshalText方法。
   105  func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error {
   106  	raw, err := checkText(input, false)
   107  	if err != nil {
   108  		return err
   109  	}
   110  	if len(raw)/2 != len(out) {
   111  		return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname)
   112  	}
   113  //在修改out之前预先验证语法。
   114  	for _, b := range raw {
   115  		if decodeNibble(b) == badNibble {
   116  			return ErrSyntax
   117  		}
   118  	}
   119  	hex.Decode(out, raw)
   120  	return nil
   121  }
   122  
   123  //大封送/取消封送作为带有0x前缀的JSON字符串。
   124  //零值封送为“0x0”。
   125  //
   126  //此时不支持负整数。试图封送他们将
   127  //返回一个错误。大于256位的值将被取消标记拒绝,但将
   128  //已正确封送。
   129  type Big big.Int
   130  
   131  //MarshalText实现Encoding.TextMarshaler
   132  func (b Big) MarshalText() ([]byte, error) {
   133  	return []byte(EncodeBig((*big.Int)(&b))), nil
   134  }
   135  
   136  //unmashaljson实现json.unmasheler。
   137  func (b *Big) UnmarshalJSON(input []byte) error {
   138  	if !isString(input) {
   139  		return errNonString(bigT)
   140  	}
   141  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT)
   142  }
   143  
   144  //UnmarshalText实现编码。textUnmarshaller
   145  func (b *Big) UnmarshalText(input []byte) error {
   146  	raw, err := checkNumberText(input)
   147  	if err != nil {
   148  		return err
   149  	}
   150  	if len(raw) > 64 {
   151  		return ErrBig256Range
   152  	}
   153  	words := make([]big.Word, len(raw)/bigWordNibbles+1)
   154  	end := len(raw)
   155  	for i := range words {
   156  		start := end - bigWordNibbles
   157  		if start < 0 {
   158  			start = 0
   159  		}
   160  		for ri := start; ri < end; ri++ {
   161  			nib := decodeNibble(raw[ri])
   162  			if nib == badNibble {
   163  				return ErrSyntax
   164  			}
   165  			words[i] *= 16
   166  			words[i] += big.Word(nib)
   167  		}
   168  		end = start
   169  	}
   170  	var dec big.Int
   171  	dec.SetBits(words)
   172  	*b = (Big)(dec)
   173  	return nil
   174  }
   175  
   176  //ToInt将b转换为big.int。
   177  func (b *Big) ToInt() *big.Int {
   178  	return (*big.Int)(b)
   179  }
   180  
   181  //字符串返回b的十六进制编码。
   182  func (b *Big) String() string {
   183  	return EncodeBig(b.ToInt())
   184  }
   185  
   186  //uint64以带有0x前缀的JSON字符串封送/取消封送。
   187  //零值封送为“0x0”。
   188  type Uint64 uint64
   189  
   190  //MarshalText实现Encoding.TextMarshaler。
   191  func (b Uint64) MarshalText() ([]byte, error) {
   192  	buf := make([]byte, 2, 10)
   193  	copy(buf, `0x`)
   194  	buf = strconv.AppendUint(buf, uint64(b), 16)
   195  	return buf, nil
   196  }
   197  
   198  //unmashaljson实现json.unmasheler。
   199  func (b *Uint64) UnmarshalJSON(input []byte) error {
   200  	if !isString(input) {
   201  		return errNonString(uint64T)
   202  	}
   203  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T)
   204  }
   205  
   206  //UnmarshalText实现编码。textUnmarshaller
   207  func (b *Uint64) UnmarshalText(input []byte) error {
   208  	raw, err := checkNumberText(input)
   209  	if err != nil {
   210  		return err
   211  	}
   212  	if len(raw) > 16 {
   213  		return ErrUint64Range
   214  	}
   215  	var dec uint64
   216  	for _, byte := range raw {
   217  		nib := decodeNibble(byte)
   218  		if nib == badNibble {
   219  			return ErrSyntax
   220  		}
   221  		dec *= 16
   222  		dec += nib
   223  	}
   224  	*b = Uint64(dec)
   225  	return nil
   226  }
   227  
   228  //字符串返回b的十六进制编码。
   229  func (b Uint64) String() string {
   230  	return EncodeUint64(uint64(b))
   231  }
   232  
   233  //uint将封送/取消封送为前缀为0x的JSON字符串。
   234  //零值封送为“0x0”。
   235  type Uint uint
   236  
   237  //MarshalText实现Encoding.TextMarshaler。
   238  func (b Uint) MarshalText() ([]byte, error) {
   239  	return Uint64(b).MarshalText()
   240  }
   241  
   242  //unmashaljson实现json.unmasheler。
   243  func (b *Uint) UnmarshalJSON(input []byte) error {
   244  	if !isString(input) {
   245  		return errNonString(uintT)
   246  	}
   247  	return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT)
   248  }
   249  
   250  //UnmarshalText实现encoding.textUnmarshaller。
   251  func (b *Uint) UnmarshalText(input []byte) error {
   252  	var u64 Uint64
   253  	err := u64.UnmarshalText(input)
   254  	if u64 > Uint64(^uint(0)) || err == ErrUint64Range {
   255  		return ErrUintRange
   256  	} else if err != nil {
   257  		return err
   258  	}
   259  	*b = Uint(u64)
   260  	return nil
   261  }
   262  
   263  //字符串返回b的十六进制编码。
   264  func (b Uint) String() string {
   265  	return EncodeUint64(uint64(b))
   266  }
   267  
   268  func isString(input []byte) bool {
   269  	return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"'
   270  }
   271  
   272  func bytesHave0xPrefix(input []byte) bool {
   273  	return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X')
   274  }
   275  
   276  func checkText(input []byte, wantPrefix bool) ([]byte, error) {
   277  	if len(input) == 0 {
   278  return nil, nil //允许空字符串
   279  	}
   280  	if bytesHave0xPrefix(input) {
   281  		input = input[2:]
   282  	} else if wantPrefix {
   283  		return nil, ErrMissingPrefix
   284  	}
   285  	if len(input)%2 != 0 {
   286  		return nil, ErrOddLength
   287  	}
   288  	return input, nil
   289  }
   290  
   291  func checkNumberText(input []byte) (raw []byte, err error) {
   292  	if len(input) == 0 {
   293  return nil, nil //允许空字符串
   294  	}
   295  	if !bytesHave0xPrefix(input) {
   296  		return nil, ErrMissingPrefix
   297  	}
   298  	input = input[2:]
   299  	if len(input) == 0 {
   300  		return nil, ErrEmptyNumber
   301  	}
   302  	if len(input) > 1 && input[0] == '0' {
   303  		return nil, ErrLeadingZero
   304  	}
   305  	return input, nil
   306  }
   307  
   308  func wrapTypeError(err error, typ reflect.Type) error {
   309  	if _, ok := err.(*decError); ok {
   310  		return &json.UnmarshalTypeError{Value: err.Error(), Type: typ}
   311  	}
   312  	return err
   313  }
   314  
   315  func errNonString(typ reflect.Type) error {
   316  	return &json.UnmarshalTypeError{Value: "non-string", Type: typ}
   317  }
   318