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