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