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 }