github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/common/hexutil/json.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:34</date> 10 //</624450073622745088> 11 12 13 package hexutil 14 15 import ( 16 "encoding/hex" 17 "encoding/json" 18 "fmt" 19 "math/big" 20 "reflect" 21 "strconv" 22 ) 23 24 var ( 25 bytesT = reflect.TypeOf(Bytes(nil)) 26 bigT = reflect.TypeOf((*Big)(nil)) 27 uintT = reflect.TypeOf(Uint(0)) 28 uint64T = reflect.TypeOf(Uint64(0)) 29 ) 30 31 //字节封送/取消封送为带0x前缀的JSON字符串。 32 //空切片封送为“0x”。 33 type Bytes []byte 34 35 //MarshalText实现Encoding.TextMarshaler 36 func (b Bytes) MarshalText() ([]byte, error) { 37 result := make([]byte, len(b)*2+2) 38 copy(result, `0x`) 39 hex.Encode(result[2:], b) 40 return result, nil 41 } 42 43 //unmashaljson实现json.unmasheler。 44 func (b *Bytes) UnmarshalJSON(input []byte) error { 45 if !isString(input) { 46 return errNonString(bytesT) 47 } 48 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bytesT) 49 } 50 51 //UnmarshalText实现encoding.textUnmarshaller。 52 func (b *Bytes) UnmarshalText(input []byte) error { 53 raw, err := checkText(input, true) 54 if err != nil { 55 return err 56 } 57 dec := make([]byte, len(raw)/2) 58 if _, err = hex.Decode(dec, raw); err != nil { 59 err = mapError(err) 60 } else { 61 *b = dec 62 } 63 return err 64 } 65 66 //字符串返回b的十六进制编码。 67 func (b Bytes) String() string { 68 return Encode(b) 69 } 70 71 //unmarshalfixedjson将输入解码为带0x前缀的字符串。输出长度 72 //确定所需的输入长度。此函数通常用于实现 73 //固定大小类型的unmashaljson方法。 74 func UnmarshalFixedJSON(typ reflect.Type, input, out []byte) error { 75 if !isString(input) { 76 return errNonString(typ) 77 } 78 return wrapTypeError(UnmarshalFixedText(typ.String(), input[1:len(input)-1], out), typ) 79 } 80 81 //unmarshalfixedtext将输入解码为带0x前缀的字符串。输出长度 82 //确定所需的输入长度。此函数通常用于实现 83 //为固定大小类型取消标记文本方法。 84 func UnmarshalFixedText(typname string, input, out []byte) error { 85 raw, err := checkText(input, true) 86 if err != nil { 87 return err 88 } 89 if len(raw)/2 != len(out) { 90 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 91 } 92 //在修改out之前预先验证语法。 93 for _, b := range raw { 94 if decodeNibble(b) == badNibble { 95 return ErrSyntax 96 } 97 } 98 hex.Decode(out, raw) 99 return nil 100 } 101 102 //unmarshalfixedUnprefixedText将输入解码为带可选0x前缀的字符串。这个 103 //输出长度决定所需的输入长度。此函数通常用于 104 //为固定大小类型实现UnmarshalText方法。 105 func UnmarshalFixedUnprefixedText(typname string, input, out []byte) error { 106 raw, err := checkText(input, false) 107 if err != nil { 108 return err 109 } 110 if len(raw)/2 != len(out) { 111 return fmt.Errorf("hex string has length %d, want %d for %s", len(raw), len(out)*2, typname) 112 } 113 //在修改out之前预先验证语法。 114 for _, b := range raw { 115 if decodeNibble(b) == badNibble { 116 return ErrSyntax 117 } 118 } 119 hex.Decode(out, raw) 120 return nil 121 } 122 123 //大封送/取消封送作为带有0x前缀的JSON字符串。 124 //零值封送为“0x0”。 125 // 126 //此时不支持负整数。试图封送他们将 127 //返回一个错误。大于256位的值将被取消标记拒绝,但将 128 //已正确封送。 129 type Big big.Int 130 131 //MarshalText实现Encoding.TextMarshaler 132 func (b Big) MarshalText() ([]byte, error) { 133 return []byte(EncodeBig((*big.Int)(&b))), nil 134 } 135 136 //unmashaljson实现json.unmasheler。 137 func (b *Big) UnmarshalJSON(input []byte) error { 138 if !isString(input) { 139 return errNonString(bigT) 140 } 141 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), bigT) 142 } 143 144 //UnmarshalText实现编码。textUnmarshaller 145 func (b *Big) UnmarshalText(input []byte) error { 146 raw, err := checkNumberText(input) 147 if err != nil { 148 return err 149 } 150 if len(raw) > 64 { 151 return ErrBig256Range 152 } 153 words := make([]big.Word, len(raw)/bigWordNibbles+1) 154 end := len(raw) 155 for i := range words { 156 start := end - bigWordNibbles 157 if start < 0 { 158 start = 0 159 } 160 for ri := start; ri < end; ri++ { 161 nib := decodeNibble(raw[ri]) 162 if nib == badNibble { 163 return ErrSyntax 164 } 165 words[i] *= 16 166 words[i] += big.Word(nib) 167 } 168 end = start 169 } 170 var dec big.Int 171 dec.SetBits(words) 172 *b = (Big)(dec) 173 return nil 174 } 175 176 //ToInt将b转换为big.int。 177 func (b *Big) ToInt() *big.Int { 178 return (*big.Int)(b) 179 } 180 181 //字符串返回b的十六进制编码。 182 func (b *Big) String() string { 183 return EncodeBig(b.ToInt()) 184 } 185 186 //uint64以带有0x前缀的JSON字符串封送/取消封送。 187 //零值封送为“0x0”。 188 type Uint64 uint64 189 190 //MarshalText实现Encoding.TextMarshaler。 191 func (b Uint64) MarshalText() ([]byte, error) { 192 buf := make([]byte, 2, 10) 193 copy(buf, `0x`) 194 buf = strconv.AppendUint(buf, uint64(b), 16) 195 return buf, nil 196 } 197 198 //unmashaljson实现json.unmasheler。 199 func (b *Uint64) UnmarshalJSON(input []byte) error { 200 if !isString(input) { 201 return errNonString(uint64T) 202 } 203 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uint64T) 204 } 205 206 //UnmarshalText实现编码。textUnmarshaller 207 func (b *Uint64) UnmarshalText(input []byte) error { 208 raw, err := checkNumberText(input) 209 if err != nil { 210 return err 211 } 212 if len(raw) > 16 { 213 return ErrUint64Range 214 } 215 var dec uint64 216 for _, byte := range raw { 217 nib := decodeNibble(byte) 218 if nib == badNibble { 219 return ErrSyntax 220 } 221 dec *= 16 222 dec += nib 223 } 224 *b = Uint64(dec) 225 return nil 226 } 227 228 //字符串返回b的十六进制编码。 229 func (b Uint64) String() string { 230 return EncodeUint64(uint64(b)) 231 } 232 233 //uint将封送/取消封送为前缀为0x的JSON字符串。 234 //零值封送为“0x0”。 235 type Uint uint 236 237 //MarshalText实现Encoding.TextMarshaler。 238 func (b Uint) MarshalText() ([]byte, error) { 239 return Uint64(b).MarshalText() 240 } 241 242 //unmashaljson实现json.unmasheler。 243 func (b *Uint) UnmarshalJSON(input []byte) error { 244 if !isString(input) { 245 return errNonString(uintT) 246 } 247 return wrapTypeError(b.UnmarshalText(input[1:len(input)-1]), uintT) 248 } 249 250 //UnmarshalText实现encoding.textUnmarshaller。 251 func (b *Uint) UnmarshalText(input []byte) error { 252 var u64 Uint64 253 err := u64.UnmarshalText(input) 254 if u64 > Uint64(^uint(0)) || err == ErrUint64Range { 255 return ErrUintRange 256 } else if err != nil { 257 return err 258 } 259 *b = Uint(u64) 260 return nil 261 } 262 263 //字符串返回b的十六进制编码。 264 func (b Uint) String() string { 265 return EncodeUint64(uint64(b)) 266 } 267 268 func isString(input []byte) bool { 269 return len(input) >= 2 && input[0] == '"' && input[len(input)-1] == '"' 270 } 271 272 func bytesHave0xPrefix(input []byte) bool { 273 return len(input) >= 2 && input[0] == '0' && (input[1] == 'x' || input[1] == 'X') 274 } 275 276 func checkText(input []byte, wantPrefix bool) ([]byte, error) { 277 if len(input) == 0 { 278 return nil, nil //允许空字符串 279 } 280 if bytesHave0xPrefix(input) { 281 input = input[2:] 282 } else if wantPrefix { 283 return nil, ErrMissingPrefix 284 } 285 if len(input)%2 != 0 { 286 return nil, ErrOddLength 287 } 288 return input, nil 289 } 290 291 func checkNumberText(input []byte) (raw []byte, err error) { 292 if len(input) == 0 { 293 return nil, nil //允许空字符串 294 } 295 if !bytesHave0xPrefix(input) { 296 return nil, ErrMissingPrefix 297 } 298 input = input[2:] 299 if len(input) == 0 { 300 return nil, ErrEmptyNumber 301 } 302 if len(input) > 1 && input[0] == '0' { 303 return nil, ErrLeadingZero 304 } 305 return input, nil 306 } 307 308 func wrapTypeError(err error, typ reflect.Type) error { 309 if _, ok := err.(*decError); ok { 310 return &json.UnmarshalTypeError{Value: err.Error(), Type: typ} 311 } 312 return err 313 } 314 315 func errNonString(typ reflect.Type) error { 316 return &json.UnmarshalTypeError{Value: "non-string", Type: typ} 317 } 318