git.gammaspectra.live/P2Pool/go-json@v0.99.0/internal/decoder/uint.go (about) 1 package decoder 2 3 import ( 4 "fmt" 5 "reflect" 6 "unsafe" 7 8 "git.gammaspectra.live/P2Pool/go-json/internal/errors" 9 "git.gammaspectra.live/P2Pool/go-json/internal/runtime" 10 ) 11 12 type uintDecoder struct { 13 typ *runtime.Type 14 kind reflect.Kind 15 op func(unsafe.Pointer, uint64) 16 structName string 17 fieldName string 18 } 19 20 func newUintDecoder(typ *runtime.Type, structName, fieldName string, op func(unsafe.Pointer, uint64)) *uintDecoder { 21 return &uintDecoder{ 22 typ: typ, 23 kind: typ.Kind(), 24 op: op, 25 structName: structName, 26 fieldName: fieldName, 27 } 28 } 29 30 func (d *uintDecoder) typeError(buf []byte, offset int64) *errors.UnmarshalTypeError { 31 return &errors.UnmarshalTypeError{ 32 Value: fmt.Sprintf("number %s", string(buf)), 33 Type: runtime.RType2Type(d.typ), 34 Offset: offset, 35 } 36 } 37 38 var ( 39 pow10u64 = [...]uint64{ 40 1e00, 1e01, 1e02, 1e03, 1e04, 1e05, 1e06, 1e07, 1e08, 1e09, 41 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 42 } 43 pow10u64Len = len(pow10u64) 44 ) 45 46 func (d *uintDecoder) parseUint(b []byte) (uint64, error) { 47 maxDigit := len(b) 48 if maxDigit > pow10u64Len { 49 return 0, fmt.Errorf("invalid length of number") 50 } 51 sum := uint64(0) 52 for i := 0; i < maxDigit; i++ { 53 c := uint64(b[i]) - 48 54 digitValue := pow10u64[maxDigit-i-1] 55 sum += c * digitValue 56 } 57 return sum, nil 58 } 59 60 func (d *uintDecoder) decodeStreamByte(s *Stream) ([]byte, error) { 61 for { 62 switch s.char() { 63 case ' ', '\n', '\t', '\r': 64 s.cursor++ 65 continue 66 case '0': 67 s.cursor++ 68 return numZeroBuf, nil 69 case '1', '2', '3', '4', '5', '6', '7', '8', '9': 70 start := s.cursor 71 for { 72 s.cursor++ 73 if numTable[s.char()] { 74 continue 75 } else if s.char() == nul { 76 if s.read() { 77 s.cursor-- // for retry current character 78 continue 79 } 80 } 81 break 82 } 83 num := s.buf[start:s.cursor] 84 return num, nil 85 case 'n': 86 if err := nullBytes(s); err != nil { 87 return nil, err 88 } 89 return nil, nil 90 case nul: 91 if s.read() { 92 continue 93 } 94 default: 95 return nil, d.typeError([]byte{s.char()}, s.totalOffset()) 96 } 97 break 98 } 99 return nil, errors.ErrUnexpectedEndOfJSON("number(unsigned integer)", s.totalOffset()) 100 } 101 102 func (d *uintDecoder) decodeByte(buf []byte, cursor int64) ([]byte, int64, error) { 103 for { 104 switch buf[cursor] { 105 case ' ', '\n', '\t', '\r': 106 cursor++ 107 continue 108 case '0': 109 cursor++ 110 return numZeroBuf, cursor, nil 111 case '1', '2', '3', '4', '5', '6', '7', '8', '9': 112 start := cursor 113 cursor++ 114 for numTable[buf[cursor]] { 115 cursor++ 116 } 117 num := buf[start:cursor] 118 return num, cursor, nil 119 case 'n': 120 if err := validateNull(buf, cursor); err != nil { 121 return nil, 0, err 122 } 123 cursor += 4 124 return nil, cursor, nil 125 default: 126 return nil, 0, d.typeError([]byte{buf[cursor]}, cursor) 127 } 128 } 129 } 130 131 func (d *uintDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { 132 bytes, err := d.decodeStreamByte(s) 133 if err != nil { 134 return err 135 } 136 if bytes == nil { 137 return nil 138 } 139 u64, err := d.parseUint(bytes) 140 if err != nil { 141 return d.typeError(bytes, s.totalOffset()) 142 } 143 switch d.kind { 144 case reflect.Uint8: 145 if (1 << 8) <= u64 { 146 return d.typeError(bytes, s.totalOffset()) 147 } 148 case reflect.Uint16: 149 if (1 << 16) <= u64 { 150 return d.typeError(bytes, s.totalOffset()) 151 } 152 case reflect.Uint32: 153 if (1 << 32) <= u64 { 154 return d.typeError(bytes, s.totalOffset()) 155 } 156 } 157 d.op(p, u64) 158 return nil 159 } 160 161 func (d *uintDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 162 bytes, c, err := d.decodeByte(ctx.Buf, cursor) 163 if err != nil { 164 return 0, err 165 } 166 if bytes == nil { 167 return c, nil 168 } 169 cursor = c 170 u64, err := d.parseUint(bytes) 171 if err != nil { 172 return 0, d.typeError(bytes, cursor) 173 } 174 switch d.kind { 175 case reflect.Uint8: 176 if (1 << 8) <= u64 { 177 return 0, d.typeError(bytes, cursor) 178 } 179 case reflect.Uint16: 180 if (1 << 16) <= u64 { 181 return 0, d.typeError(bytes, cursor) 182 } 183 case reflect.Uint32: 184 if (1 << 32) <= u64 { 185 return 0, d.typeError(bytes, cursor) 186 } 187 } 188 d.op(p, u64) 189 return cursor, nil 190 } 191 192 func (d *uintDecoder) DecodePath(ctx *RuntimeContext, cursor, depth int64) ([][]byte, int64, error) { 193 return nil, 0, fmt.Errorf("json: uint decoder does not support decode path") 194 }