github.com/theQRL/go-zond@v0.2.1/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 "encoding/json" 22 "fmt" 23 "math/big" 24 "reflect" 25 "strconv" 26 ) 27 28 var ( 29 bytesT = reflect.TypeOf(Bytes(nil)) 30 byteszT = reflect.TypeOf(BytesZ(nil)) 31 bigT = reflect.TypeOf((*Big)(nil)) 32 uintT = reflect.TypeOf(Uint(0)) 33 uint64T = reflect.TypeOf(Uint64(0)) 34 ) 35 36 // Bytes marshals/unmarshals as a JSON string with 0x prefix. 37 // The empty slice marshals as "0x". 38 type Bytes []byte 39 40 // MarshalText implements encoding.TextMarshaler 41 func (b Bytes) MarshalText() ([]byte, error) { 42 result := make([]byte, len(b)*2+2) 43 copy(result, `0x`) 44 hex.Encode(result[2:], b) 45 return result, nil 46 } 47 48 // UnmarshalJSON implements json.Unmarshaler. 49 func (b *Bytes) UnmarshalJSON(input []byte) error { 50 if !isString(input) { 51 return errNonString(bytesT) 52 } 53 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT) 54 } 55 56 // UnmarshalText implements encoding.TextUnmarshaler. 57 func (b *Bytes) UnmarshalText(input []byte) error { 58 raw, err := checkText(input, true) 59 if err != nil { 60 return err 61 } 62 dec := make([]byte, len(raw)/2) 63 if _, err = hex.Decode(dec, raw); err != nil { 64 err = mapError(err) 65 } else { 66 *b = dec 67 } 68 return err 69 } 70 71 // String returns the hex encoding of b. 72 func (b Bytes) String() string { 73 return Encode(b) 74 } 75 76 // ImplementsGraphQLType returns true if Bytes implements the specified GraphQL type. 77 func (b Bytes) ImplementsGraphQLType(name string) bool { return name == "Bytes" } 78 79 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 80 func (b *Bytes) UnmarshalGraphQL(input interface{}) error { 81 var err error 82 switch input := input.(type) { 83 case string: 84 data, err := Decode(input) 85 if err != nil { 86 return err 87 } 88 *b = data 89 default: 90 err = fmt.Errorf("unexpected type %T for Bytes", input) 91 } 92 return err 93 } 94 95 // UnmarshalFixedJSON decodes the input as a string with 0x prefix. The length of out 96 // determines the required input length. This function is commonly used to implement the 97 // UnmarshalJSON method for fixed-size types. 98 func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error { 99 if !isString(input) { 100 return errNonString(typ) 101 } 102 return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ) 103 } 104 105 func UnmarshalFixedJSONZ(typ reflect.Type, input, out []byte) error { 106 if !isString(input) { 107 return errNonString(typ) 108 } 109 return wrapTypeError(UnmarshalFixedTextZ(typ.String(), input[1:len(input)-1], out), typ) 110 } 111 112 // UnmarshalFixedText decodes the input as a string with 0x prefix. The length of out 113 // determines the required input length. This function is commonly used to implement the 114 // UnmarshalText method for fixed-size types. 115 func UnmarshalFixedText(typname string, input, out []byte) error { 116 raw, err := checkText(input, true) 117 if err != nil { 118 return err 119 } 120 if len(raw)/2 != len(out) { 121 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 122 } 123 // Pre-verify syntax before modifying out. 124 for _, b := range raw { 125 if decodeNibble(b) == badNibble { 126 return ErrSyntax 127 } 128 } 129 hex.Decode(out, raw) 130 return nil 131 } 132 133 func UnmarshalFixedTextZ(typname string, input, out []byte) error { 134 raw, err := checkTextZ(input, true) 135 if err != nil { 136 return err 137 } 138 if len(raw)/2 != len(out) { 139 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 140 } 141 // Pre-verify syntax before modifying out. 142 for _, b := range raw { 143 if decodeNibble(b) == badNibble { 144 return ErrSyntax 145 } 146 } 147 hex.Decode(out, raw) 148 return nil 149 } 150 151 // UnmarshalFixedUnprefixedText decodes the input as a string with optional 0x prefix. The 152 // length of out determines the required input length. This function is commonly used to 153 // implement the UnmarshalText method for fixed-size types. 154 func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error { 155 raw, err := checkText(input, false) 156 if err != nil { 157 return err 158 } 159 if len(raw)/2 != len(out) { 160 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 161 } 162 // Pre-verify syntax before modifying out. 163 for _, b := range raw { 164 if decodeNibble(b) == badNibble { 165 return ErrSyntax 166 } 167 } 168 hex.Decode(out, raw) 169 return nil 170 } 171 172 // Big marshals/unmarshals as a JSON string with 0x prefix. 173 // The zero value marshals as "0x0". 174 // 175 // Negative integers are not supported at this time. Attempting to marshal them will 176 // return an error. Values larger than 256bits are rejected by Unmarshal but will be 177 // marshaled without error. 178 type Big big.Int 179 180 // MarshalText implements encoding.TextMarshaler 181 func (b Big) MarshalText() ([]byte, error) { 182 return []byte(EncodeBig((*big.Int)(&b))), nil 183 } 184 185 // UnmarshalJSON implements json.Unmarshaler. 186 func (b *Big) UnmarshalJSON(input []byte) error { 187 if !isString(input) { 188 return errNonString(bigT) 189 } 190 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT) 191 } 192 193 // UnmarshalText implements encoding.TextUnmarshaler 194 func (b *Big) UnmarshalText(input []byte) error { 195 raw, err := checkNumberText(input) 196 if err != nil { 197 return err 198 } 199 if len(raw) > 64 { 200 return ErrBig256Range 201 } 202 words := make([]big.Word, len(raw)/bigWordNibbles+1) 203 end := len(raw) 204 for i := range words { 205 start := end - bigWordNibbles 206 if start < 0 { 207 start = 0 208 } 209 for ri := start; ri < end; ri++ { 210 nib := decodeNibble(raw[ri]) 211 if nib == badNibble { 212 return ErrSyntax 213 } 214 words[i] *= 16 215 words[i] += big.Word(nib) 216 } 217 end = start 218 } 219 var dec big.Int 220 dec.SetBits(words) 221 *b = (Big)(dec) 222 return nil 223 } 224 225 // ToInt converts b to a big.Int. 226 func (b *Big) ToInt() *big.Int { 227 return (*big.Int)(b) 228 } 229 230 // String returns the hex encoding of b. 231 func (b *Big) String() string { 232 return EncodeBig(b.ToInt()) 233 } 234 235 // ImplementsGraphQLType returns true if Big implements the provided GraphQL type. 236 func (b Big) ImplementsGraphQLType(name string) bool { return name == "BigInt" } 237 238 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 239 func (b *Big) UnmarshalGraphQL(input interface{}) error { 240 var err error 241 switch input := input.(type) { 242 case string: 243 return b.UnmarshalText([]byte(input)) 244 case int32: 245 var num big.Int 246 num.SetInt64(int64(input)) 247 *b = Big(num) 248 default: 249 err = fmt.Errorf("unexpected type %T for BigInt", input) 250 } 251 return err 252 } 253 254 // Uint64 marshals/unmarshals as a JSON string with 0x prefix. 255 // The zero value marshals as "0x0". 256 type Uint64 uint64 257 258 // MarshalText implements encoding.TextMarshaler. 259 func (b Uint64) MarshalText() ([]byte, error) { 260 buf := make([]byte, 2, 10) 261 copy(buf, `0x`) 262 buf = strconv.AppendUint(buf, uint64(b), 16) 263 return buf, nil 264 } 265 266 // UnmarshalJSON implements json.Unmarshaler. 267 func (b *Uint64) UnmarshalJSON(input []byte) error { 268 if !isString(input) { 269 return errNonString(uint64T) 270 } 271 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T) 272 } 273 274 // UnmarshalText implements encoding.TextUnmarshaler 275 func (b *Uint64) UnmarshalText(input []byte) error { 276 raw, err := checkNumberText(input) 277 if err != nil { 278 return err 279 } 280 if len(raw) > 16 { 281 return ErrUint64Range 282 } 283 var dec uint64 284 for _, byte := range raw { 285 nib := decodeNibble(byte) 286 if nib == badNibble { 287 return ErrSyntax 288 } 289 dec *= 16 290 dec += nib 291 } 292 *b = Uint64(dec) 293 return nil 294 } 295 296 // String returns the hex encoding of b. 297 func (b Uint64) String() string { 298 return EncodeUint64(uint64(b)) 299 } 300 301 // ImplementsGraphQLType returns true if Uint64 implements the provided GraphQL type. 302 func (b Uint64) ImplementsGraphQLType(name string) bool { return name == "Long" } 303 304 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 305 func (b *Uint64) UnmarshalGraphQL(input interface{}) error { 306 var err error 307 switch input := input.(type) { 308 case string: 309 return b.UnmarshalText([]byte(input)) 310 case int32: 311 *b = Uint64(input) 312 default: 313 err = fmt.Errorf("unexpected type %T for Long", input) 314 } 315 return err 316 } 317 318 // Uint marshals/unmarshals as a JSON string with 0x prefix. 319 // The zero value marshals as "0x0". 320 type Uint uint 321 322 // MarshalText implements encoding.TextMarshaler. 323 func (b Uint) MarshalText() ([]byte, error) { 324 return Uint64(b).MarshalText() 325 } 326 327 // UnmarshalJSON implements json.Unmarshaler. 328 func (b *Uint) UnmarshalJSON(input []byte) error { 329 if !isString(input) { 330 return errNonString(uintT) 331 } 332 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT) 333 } 334 335 // UnmarshalText implements encoding.TextUnmarshaler. 336 func (b *Uint) UnmarshalText(input []byte) error { 337 var u64 Uint64 338 err := u64.UnmarshalText(input) 339 if u64 > Uint64(^uint(0)) || err == ErrUint64Range { 340 return ErrUintRange 341 } else if err != nil { 342 return err 343 } 344 *b = Uint(u64) 345 return nil 346 } 347 348 // String returns the hex encoding of b. 349 func (b Uint) String() string { 350 return EncodeUint64(uint64(b)) 351 } 352 353 // BytesZ marshals/unmarshals as a JSON string with Z prefix. 354 // The empty slice marshals as "Z". 355 type BytesZ []byte 356 357 // MarshalText implements encoding.TextMarshaler 358 func (b BytesZ) MarshalText() ([]byte, error) { 359 result := make([]byte, len(b)*2+1) 360 copy(result, PrefixZ) 361 hex.Encode(result[1:], b) 362 return result, nil 363 } 364 365 // UnmarshalJSON implements json.Unmarshaler. 366 func (b *BytesZ) UnmarshalJSON(input []byte) error { 367 if !isString(input) { 368 return errNonString(byteszT) 369 } 370 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT) 371 } 372 373 // UnmarshalText implements encoding.TextUnmarshaler. 374 func (b *BytesZ) UnmarshalText(input []byte) error { 375 raw, err := checkTextZ(input, true) 376 if err != nil { 377 return err 378 } 379 dec := make([]byte, len(raw)/2) 380 if _, err = hex.Decode(dec, raw); err != nil { 381 err = mapError(err) 382 } else { 383 *b = dec 384 } 385 return err 386 } 387 388 // String returns the hex encoding of b. 389 func (b BytesZ) String() string { 390 return EncodeZ(b) 391 } 392 393 // ImplementsGraphQLType returns true if BytesZ implements the specified GraphQL type. 394 func (b BytesZ) ImplementsGraphQLType(name string) bool { return name == "BytesZ" } 395 396 // UnmarshalGraphQL unmarshals the provided GraphQL query data. 397 func (b *BytesZ) UnmarshalGraphQL(input interface{}) error { 398 var err error 399 switch input := input.(type) { 400 case string: 401 data, err := DecodeZ(input) 402 if err != nil { 403 return err 404 } 405 *b = data 406 default: 407 err = fmt.Errorf("unexpected type %T for BytesZ", input) 408 } 409 return err 410 } 411 412 func isString(input []byte) bool { 413 return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' 414 } 415 416 func bytesHave0xPrefix(input []byte) bool { 417 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 418 } 419 420 func bytesHaveZPrefix(input []byte) bool { 421 return len(input) >= 1 && input[0] == 'Z' 422 } 423 424 func checkText(input []byte, wantPrefix bool) ([]byte, error) { 425 if len(input) == 0 { 426 return nil, nil // empty strings are allowed 427 } 428 if bytesHave0xPrefix(input) { 429 input = input[2:] 430 } else if wantPrefix { 431 return nil, ErrMissingPrefix 432 } 433 if len(input)%2 != 0 { 434 return nil, ErrOddLength 435 } 436 return input, nil 437 } 438 439 func checkTextZ(input []byte, wantPrefix bool) ([]byte, error) { 440 if len(input) == 0 { 441 return nil, nil // empty strings are allowed 442 } 443 if bytesHaveZPrefix(input) { 444 input = input[1:] 445 } else if wantPrefix { 446 return nil, ErrMissingPrefixZ 447 } 448 if len(input)%2 != 0 { 449 return nil, ErrOddLength 450 } 451 return input, nil 452 } 453 454 func checkNumberText(input []byte) (raw []byte, err error) { 455 if len(input) == 0 { 456 return nil, nil // empty strings are allowed 457 } 458 if !bytesHave0xPrefix(input) { 459 return nil, ErrMissingPrefix 460 } 461 input = input[2:] 462 if len(input) == 0 { 463 return nil, ErrEmptyNumber 464 } 465 if len(input) > 1 && input[0] == '0' { 466 return nil, ErrLeadingZero 467 } 468 return input, nil 469 } 470 471 func wrapTypeError(err error, typ reflect.Type) error { 472 if _, ok := err.(*decError); ok { 473 return &json.UnmarshalTypeError{Value: err.Error(), Type: typ} 474 } 475 return err 476 } 477 478 func errNonString(typ reflect.Type) error { 479 return &json.UnmarshalTypeError{Value: "non-string", Type: typ} 480 }