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