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