github.com/status-im/status-go@v1.1.0/eth-node/types/json.go (about) 1 // Code extracted from vendor/github.com/ethereum/go-ethereum/common/hexutil/json.go 2 3 package types 4 5 import ( 6 "encoding/hex" 7 "encoding/json" 8 "fmt" 9 "reflect" 10 "strconv" 11 ) 12 13 const ( 14 badNibble = ^uint64(0) 15 uintBits = 32 << (uint64(^uint(0)) >> 63) 16 ) 17 18 // Errors 19 var ( 20 ErrEmptyString = &decError{"empty hex string"} 21 ErrSyntax = &decError{"invalid hex string"} 22 ErrMissingPrefix = &decError{"hex string without 0x prefix"} 23 ErrOddLength = &decError{"hex string of odd length"} 24 ErrEmptyNumber = &decError{"hex string \"0x\""} 25 ErrLeadingZero = &decError{"hex number with leading zero digits"} 26 ErrUint64Range = &decError{"hex number > 64 bits"} 27 ErrUintRange = &decError{fmt.Sprintf("hex number > %d bits", uintBits)} 28 ErrBig256Range = &decError{"hex number > 256 bits"} 29 ) 30 31 type decError struct{ msg string } 32 33 func (err decError) Error() string { return err.msg } 34 35 func decodeNibble(in byte) uint64 { 36 switch { 37 case in >= '0' && in <= '9': 38 return uint64(in - '0') 39 case in >= 'A' && in <= 'F': 40 return uint64(in - 'A' + 10) 41 case in >= 'a' && in <= 'f': 42 return uint64(in - 'a' + 10) 43 default: 44 return badNibble 45 } 46 } 47 48 // UnmarshalText implements encoding.TextUnmarshaler. 49 func (b *HexBytes) UnmarshalText(input []byte) error { 50 raw, err := checkText(input, true) 51 if err != nil { 52 return err 53 } 54 dec := make([]byte, len(raw)/2) 55 if _, err = hex.Decode(dec, raw); err != nil { 56 err = mapError(err) 57 } else { 58 *b = dec 59 } 60 return err 61 } 62 63 // UnmarshalFixedHexText decodes the input as a string with 0x prefix. The length of out 64 // determines the required input length. This function is commonly used to implement the 65 // UnmarshalText method for fixed-size types. 66 func UnmarshalFixedHexText(typname string, input, out []byte) error { 67 raw, err := checkText(input, true) 68 if err != nil { 69 return err 70 } 71 if len(raw)/2 != len(out) { 72 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 73 } 74 // Pre-verify syntax before modifying out. 75 for _, b := range raw { 76 if decodeNibble(b) == badNibble { 77 return ErrSyntax 78 } 79 } 80 _, err = hex.Decode(out, raw) 81 return err 82 } 83 84 // String returns the hex encoding of b. 85 func (b HexBytes) String() string { 86 return EncodeHex(b) 87 } 88 89 // EncodeHex encodes b as a hex string with 0x prefix. 90 func EncodeHex(b []byte) string { 91 enc := make([]byte, len(b)*2+2) 92 copy(enc, "0x") 93 hex.Encode(enc[2:], b) 94 return string(enc) 95 } 96 97 // EncodeHex encodes bs as a hex strings with 0x prefix. 98 func EncodeHexes(bs [][]byte) []string { 99 result := make([]string, len(bs)) 100 for i, b := range bs { 101 result[i] = EncodeHex(b) 102 } 103 return result 104 } 105 106 // DecodeHex decodes a hex string with 0x prefix. 107 func DecodeHex(input string) ([]byte, error) { 108 if len(input) == 0 { 109 return nil, ErrEmptyString 110 } 111 if !has0xPrefix(input) { 112 return nil, ErrMissingPrefix 113 } 114 b, err := hex.DecodeString(input[2:]) 115 if err != nil { 116 err = mapError(err) 117 } 118 return b, err 119 } 120 121 // MustDecodeHex decodes a hex string with 0x prefix. It panics for invalid input. 122 func MustDecodeHex(input string) []byte { 123 dec, err := DecodeHex(input) 124 if err != nil { 125 panic(err) 126 } 127 return dec 128 } 129 130 func isString(input []byte) bool { 131 return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' 132 } 133 134 func bytesHave0xPrefix(input []byte) bool { 135 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 136 } 137 138 func checkText(input []byte, wantPrefix bool) ([]byte, error) { 139 if len(input) == 0 { 140 return nil, nil // empty strings are allowed 141 } 142 if bytesHave0xPrefix(input) { 143 input = input[2:] 144 } else if wantPrefix { 145 return nil, ErrMissingPrefix 146 } 147 if len(input)%2 != 0 { 148 return nil, ErrOddLength 149 } 150 return input, nil 151 } 152 153 func mapError(err error) error { 154 if err, ok := err.(*strconv.NumError); ok { 155 switch err.Err { 156 case strconv.ErrRange: 157 return ErrUint64Range 158 case strconv.ErrSyntax: 159 return ErrSyntax 160 } 161 } 162 if _, ok := err.(hex.InvalidByteError); ok { 163 return ErrSyntax 164 } 165 if err == hex.ErrLength { 166 return ErrOddLength 167 } 168 return err 169 } 170 171 func wrapTypeError(err error, typ reflect.Type) error { 172 if _, ok := err.(*decError); ok { 173 return &json.UnmarshalTypeError{Value: err.Error(), Type: typ} 174 } 175 return err 176 } 177 178 func errNonString(typ reflect.Type) error { 179 return &json.UnmarshalTypeError{Value: "non-string", Type: typ} 180 }