github.com/avence12/go-ethereum@v1.5.10-0.20170320123548-1dfd65f6d047/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) 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) 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 // Big marshals/unmarshals as a JSON string with 0x prefix. 94 // The zero value marshals as "0x0". 95 // 96 // Negative integers are not supported at this time. Attempting to marshal them will 97 // return an error. Values larger than 256bits are rejected by Unmarshal but will be 98 // marshaled without error. 99 type Big big.Int 100 101 // MarshalText implements encoding.TextMarshaler 102 func (b Big) MarshalText() ([]byte, error) { 103 return []byte(EncodeBig((*big.Int)(&b))), nil 104 } 105 106 // UnmarshalJSON implements json.Unmarshaler. 107 func (b *Big) UnmarshalJSON(input []byte) error { 108 if !isString(input) { 109 return errNonString 110 } 111 return b.UnmarshalText(input[1 : len(input)-1]) 112 } 113 114 // UnmarshalText implements encoding.TextUnmarshaler 115 func (b *Big) UnmarshalText(input []byte) error { 116 raw, err := checkNumberText(input) 117 if err != nil { 118 return err 119 } 120 if len(raw) > 64 { 121 return ErrBig256Range 122 } 123 words := make([]big.Word, len(raw)/bigWordNibbles+1) 124 end := len(raw) 125 for i := range words { 126 start := end - bigWordNibbles 127 if start < 0 { 128 start = 0 129 } 130 for ri := start; ri < end; ri++ { 131 nib := decodeNibble(raw[ri]) 132 if nib == badNibble { 133 return ErrSyntax 134 } 135 words[i] *= 16 136 words[i] += big.Word(nib) 137 } 138 end = start 139 } 140 var dec big.Int 141 dec.SetBits(words) 142 *b = (Big)(dec) 143 return nil 144 } 145 146 // ToInt converts b to a big.Int. 147 func (b *Big) ToInt() *big.Int { 148 return (*big.Int)(b) 149 } 150 151 // String returns the hex encoding of b. 152 func (b *Big) String() string { 153 return EncodeBig(b.ToInt()) 154 } 155 156 // Uint64 marshals/unmarshals as a JSON string with 0x prefix. 157 // The zero value marshals as "0x0". 158 type Uint64 uint64 159 160 // MarshalText implements encoding.TextMarshaler. 161 func (b Uint64) MarshalText() ([]byte, error) { 162 buf := make([]byte, 2, 10) 163 copy(buf, `0x`) 164 buf = strconv.AppendUint(buf, uint64(b), 16) 165 return buf, nil 166 } 167 168 // UnmarshalJSON implements json.Unmarshaler. 169 func (b *Uint64) UnmarshalJSON(input []byte) error { 170 if !isString(input) { 171 return errNonString 172 } 173 return b.UnmarshalText(input[1 : len(input)-1]) 174 } 175 176 // UnmarshalText implements encoding.TextUnmarshaler 177 func (b *Uint64) UnmarshalText(input []byte) error { 178 raw, err := checkNumberText(input) 179 if err != nil { 180 return err 181 } 182 if len(raw) > 16 { 183 return ErrUint64Range 184 } 185 var dec uint64 186 for _, byte := range raw { 187 nib := decodeNibble(byte) 188 if nib == badNibble { 189 return ErrSyntax 190 } 191 dec *= 16 192 dec += uint64(nib) 193 } 194 *b = Uint64(dec) 195 return nil 196 } 197 198 // String returns the hex encoding of b. 199 func (b Uint64) String() string { 200 return EncodeUint64(uint64(b)) 201 } 202 203 // Uint marshals/unmarshals as a JSON string with 0x prefix. 204 // The zero value marshals as "0x0". 205 type Uint uint 206 207 // MarshalText implements encoding.TextMarshaler. 208 func (b Uint) MarshalText() ([]byte, error) { 209 return Uint64(b).MarshalText() 210 } 211 212 // UnmarshalJSON implements json.Unmarshaler. 213 func (b *Uint) UnmarshalJSON(input []byte) error { 214 if !isString(input) { 215 return errNonString 216 } 217 return b.UnmarshalText(input[1 : len(input)-1]) 218 } 219 220 // UnmarshalText implements encoding.TextUnmarshaler. 221 func (b *Uint) UnmarshalText(input []byte) error { 222 var u64 Uint64 223 err := u64.UnmarshalText(input) 224 if u64 > Uint64(^uint(0)) || err == ErrUint64Range { 225 return ErrUintRange 226 } else if err != nil { 227 return err 228 } 229 *b = Uint(u64) 230 return nil 231 } 232 233 // String returns the hex encoding of b. 234 func (b Uint) String() string { 235 return EncodeUint64(uint64(b)) 236 } 237 238 func isString(input []byte) bool { 239 return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' 240 } 241 242 func bytesHave0xPrefix(input []byte) bool { 243 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 244 } 245 246 func checkText(input []byte) ([]byte, error) { 247 if len(input) == 0 { 248 return nil, nil // empty strings are allowed 249 } 250 if !bytesHave0xPrefix(input) { 251 return nil, ErrMissingPrefix 252 } 253 input = input[2:] 254 if len(input)%2 != 0 { 255 return nil, ErrOddLength 256 } 257 return input, nil 258 } 259 260 func checkNumberText(input []byte) (raw []byte, err error) { 261 if len(input) == 0 { 262 return nil, nil // empty strings are allowed 263 } 264 if !bytesHave0xPrefix(input) { 265 return nil, ErrMissingPrefix 266 } 267 input = input[2:] 268 if len(input) == 0 { 269 return nil, ErrEmptyNumber 270 } 271 if len(input) > 1 && input[0] == '0' { 272 return nil, ErrLeadingZero 273 } 274 return input, nil 275 }