github.com/bingoohuang/gg@v0.0.0-20240325092523-45da7dee9335/pkg/jsoni/reflect_native.go (about) 1 package jsoni 2 3 import ( 4 "context" 5 "encoding/base64" 6 "reflect" 7 "strconv" 8 "unsafe" 9 10 "github.com/modern-go/reflect2" 11 ) 12 13 const ptrSize = 32 << (^uintptr(0) >> 63) 14 15 func createEncoderOfNative(ctx *ctx, typ reflect2.Type) ValEncoder { 16 if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { 17 return &base64Codec{sliceDecoder: decoderOfSlice(ctx, typ)} 18 } 19 typeName := typ.String() 20 kind := typ.Kind() 21 switch kind { 22 case reflect.String: 23 if typeName != "string" { 24 return encoderOfType(ctx, PtrElem((*string)(nil))) 25 } 26 return &stringCodec{} 27 case reflect.Int: 28 if typeName != "int" { 29 return encoderOfType(ctx, PtrElem((*int)(nil))) 30 } 31 if strconv.IntSize == 32 { 32 return &int32Codec{} 33 } 34 return &int64Codec{} 35 case reflect.Int8: 36 if typeName != "int8" { 37 return encoderOfType(ctx, PtrElem((*int8)(nil))) 38 } 39 return &int8Codec{} 40 case reflect.Int16: 41 if typeName != "int16" { 42 return encoderOfType(ctx, PtrElem((*int16)(nil))) 43 } 44 return &int16Codec{} 45 case reflect.Int32: 46 if typeName != "int32" { 47 return encoderOfType(ctx, PtrElem((*int32)(nil))) 48 } 49 return &int32Codec{} 50 case reflect.Int64: 51 if typeName != "int64" { 52 return encoderOfType(ctx, PtrElem((*int64)(nil))) 53 } 54 if ctx.int64AsString { 55 return &stringModeNumberEncoder{&int64Codec{}} 56 } 57 return &int64Codec{} 58 case reflect.Uint: 59 if typeName != "uint" { 60 return encoderOfType(ctx, PtrElem((*uint)(nil))) 61 } 62 if strconv.IntSize == 32 { 63 return &uint32Codec{} 64 } 65 return &uint64Codec{} 66 case reflect.Uint8: 67 if typeName != "uint8" { 68 return encoderOfType(ctx, PtrElem((*uint8)(nil))) 69 } 70 return &uint8Codec{} 71 case reflect.Uint16: 72 if typeName != "uint16" { 73 return encoderOfType(ctx, PtrElem((*uint16)(nil))) 74 } 75 return &uint16Codec{} 76 case reflect.Uint32: 77 if typeName != "uint32" { 78 return encoderOfType(ctx, PtrElem((*uint32)(nil))) 79 } 80 return &uint32Codec{} 81 case reflect.Uintptr: 82 if typeName != "uintptr" { 83 return encoderOfType(ctx, PtrElem((*uintptr)(nil))) 84 } 85 if ptrSize == 32 { 86 return &uint32Codec{} 87 } 88 return &uint64Codec{} 89 case reflect.Uint64: 90 if typeName != "uint64" { 91 return encoderOfType(ctx, PtrElem((*uint64)(nil))) 92 } 93 if ctx.int64AsString { 94 return &stringModeNumberEncoder{&uint64Codec{}} 95 } 96 return &uint64Codec{} 97 case reflect.Float32: 98 if typeName != "float32" { 99 return encoderOfType(ctx, PtrElem((*float32)(nil))) 100 } 101 return &float32Codec{} 102 case reflect.Float64: 103 if typeName != "float64" { 104 return encoderOfType(ctx, PtrElem((*float64)(nil))) 105 } 106 return &float64Codec{} 107 case reflect.Bool: 108 if typeName != "bool" { 109 return encoderOfType(ctx, PtrElem((*bool)(nil))) 110 } 111 return &boolCodec{} 112 } 113 return nil 114 } 115 116 func createDecoderOfNative(ctx *ctx, typ reflect2.Type) ValDecoder { 117 if typ.Kind() == reflect.Slice && typ.(reflect2.SliceType).Elem().Kind() == reflect.Uint8 { 118 return &base64Codec{sliceDecoder: decoderOfSlice(ctx, typ)} 119 } 120 typeName := typ.String() 121 switch typ.Kind() { 122 case reflect.String: 123 if typeName != "string" { 124 return decoderOfType(ctx, PtrElem((*string)(nil))) 125 } 126 return &stringCodec{} 127 case reflect.Int: 128 if typeName != "int" { 129 return decoderOfType(ctx, PtrElem((*int)(nil))) 130 } 131 if strconv.IntSize == 32 { 132 return &int32Codec{} 133 } 134 return &int64Codec{} 135 case reflect.Int8: 136 if typeName != "int8" { 137 return decoderOfType(ctx, PtrElem((*int8)(nil))) 138 } 139 return &int8Codec{} 140 case reflect.Int16: 141 if typeName != "int16" { 142 return decoderOfType(ctx, PtrElem((*int16)(nil))) 143 } 144 return &int16Codec{} 145 case reflect.Int32: 146 if typeName != "int32" { 147 return decoderOfType(ctx, PtrElem((*int32)(nil))) 148 } 149 return &int32Codec{} 150 case reflect.Int64: 151 if typeName != "int64" { 152 return decoderOfType(ctx, PtrElem((*int64)(nil))) 153 } 154 if ctx.int64AsString { 155 return &stringModeNumberCompatibleDecoder{&int64Codec{}} 156 } 157 return &int64Codec{} 158 case reflect.Uint: 159 if typeName != "uint" { 160 return decoderOfType(ctx, PtrElem((*uint)(nil))) 161 } 162 if strconv.IntSize == 32 { 163 return &uint32Codec{} 164 } 165 return &uint64Codec{} 166 case reflect.Uint8: 167 if typeName != "uint8" { 168 return decoderOfType(ctx, PtrElem((*uint8)(nil))) 169 } 170 return &uint8Codec{} 171 case reflect.Uint16: 172 if typeName != "uint16" { 173 return decoderOfType(ctx, PtrElem((*uint16)(nil))) 174 } 175 return &uint16Codec{} 176 case reflect.Uint32: 177 if typeName != "uint32" { 178 return decoderOfType(ctx, PtrElem((*uint32)(nil))) 179 } 180 return &uint32Codec{} 181 case reflect.Uintptr: 182 if typeName != "uintptr" { 183 return decoderOfType(ctx, PtrElem((*uintptr)(nil))) 184 } 185 if ptrSize == 32 { 186 return &uint32Codec{} 187 } 188 return &uint64Codec{} 189 case reflect.Uint64: 190 if typeName != "uint64" { 191 return decoderOfType(ctx, PtrElem((*uint64)(nil))) 192 } 193 if ctx.int64AsString { 194 return &stringModeNumberCompatibleDecoder{&int64Codec{}} 195 } 196 return &uint64Codec{} 197 case reflect.Float32: 198 if typeName != "float32" { 199 return decoderOfType(ctx, PtrElem((*float32)(nil))) 200 } 201 return &float32Codec{} 202 case reflect.Float64: 203 if typeName != "float64" { 204 return decoderOfType(ctx, PtrElem((*float64)(nil))) 205 } 206 return &float64Codec{} 207 case reflect.Bool: 208 if typeName != "bool" { 209 return decoderOfType(ctx, PtrElem((*bool)(nil))) 210 } 211 return &boolCodec{} 212 } 213 return nil 214 } 215 216 type stringCodec struct{} 217 218 func (c *stringCodec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 219 *((*string)(ptr)) = iter.ReadString() 220 } 221 222 func (c *stringCodec) Encode(ctx context.Context, ptr unsafe.Pointer, stream *Stream) { 223 s := *((*string)(ptr)) 224 225 if writeRawBytesIfClearQuotes(ctx, s, stream) { 226 return 227 } 228 229 stream.WriteString(s) 230 } 231 232 func (c *stringCodec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 233 return *((*string)(p)) == "" 234 } 235 236 type int8Codec struct{} 237 238 func (c *int8Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 239 if !iter.ReadNil() { 240 *((*int8)(ptr)) = iter.ReadInt8() 241 } 242 } 243 244 func (c *int8Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 245 stream.WriteInt8(*((*int8)(ptr))) 246 } 247 248 func (c *int8Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 249 return *((*int8)(p)) == 0 250 } 251 252 type int16Codec struct{} 253 254 func (c *int16Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 255 if !iter.ReadNil() { 256 *((*int16)(ptr)) = iter.ReadInt16() 257 } 258 } 259 260 func (c *int16Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 261 stream.WriteInt16(*((*int16)(ptr))) 262 } 263 264 func (c *int16Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 265 return *((*int16)(p)) == 0 266 } 267 268 type int32Codec struct{} 269 270 func (c *int32Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 271 if !iter.ReadNil() { 272 *((*int32)(ptr)) = iter.ReadInt32() 273 } 274 } 275 276 func (c *int32Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 277 stream.WriteInt32(*((*int32)(ptr))) 278 } 279 280 func (c *int32Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 281 return *((*int32)(p)) == 0 282 } 283 284 type int64Codec struct{} 285 286 func (c *int64Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 287 if !iter.ReadNil() { 288 *((*int64)(ptr)) = iter.ReadInt64() 289 } 290 } 291 292 func (c *int64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 293 stream.WriteInt64(*((*int64)(ptr))) 294 } 295 296 func (c *int64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 297 return *((*int64)(p)) == 0 298 } 299 300 type uint8Codec struct{} 301 302 func (c *uint8Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 303 if !iter.ReadNil() { 304 *((*uint8)(ptr)) = iter.ReadUint8() 305 } 306 } 307 308 func (c *uint8Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 309 stream.WriteUint8(*((*uint8)(ptr))) 310 } 311 312 func (c *uint8Codec) IsEmpty(_ context.Context, ptr unsafe.Pointer, _ bool) bool { 313 return *((*uint8)(ptr)) == 0 314 } 315 316 type uint16Codec struct{} 317 318 func (c *uint16Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 319 if !iter.ReadNil() { 320 *((*uint16)(ptr)) = iter.ReadUint16() 321 } 322 } 323 324 func (c *uint16Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 325 stream.WriteUint16(*((*uint16)(ptr))) 326 } 327 328 func (c *uint16Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 329 return *((*uint16)(p)) == 0 330 } 331 332 type uint32Codec struct{} 333 334 func (c *uint32Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 335 if !iter.ReadNil() { 336 *((*uint32)(ptr)) = iter.ReadUint32() 337 } 338 } 339 340 func (c *uint32Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 341 stream.WriteUint32(*((*uint32)(ptr))) 342 } 343 344 func (c *uint32Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 345 return *((*uint32)(p)) == 0 346 } 347 348 type uint64Codec struct{} 349 350 func (c *uint64Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 351 if !iter.ReadNil() { 352 *((*uint64)(ptr)) = iter.ReadUint64() 353 } 354 } 355 356 func (c *uint64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 357 stream.WriteUint64(*((*uint64)(ptr))) 358 } 359 360 func (c *uint64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 361 return *((*uint64)(p)) == 0 362 } 363 364 type float32Codec struct{} 365 366 func (c *float32Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 367 if !iter.ReadNil() { 368 *((*float32)(ptr)) = iter.ReadFloat32() 369 } 370 } 371 372 func (c *float32Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 373 stream.WriteFloat32(*((*float32)(ptr))) 374 } 375 376 func (c *float32Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 377 return *((*float32)(p)) == 0 378 } 379 380 type float64Codec struct{} 381 382 func (c *float64Codec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 383 if !iter.ReadNil() { 384 *((*float64)(ptr)) = iter.ReadFloat64() 385 } 386 } 387 388 func (c *float64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 389 stream.WriteFloat64(*((*float64)(ptr))) 390 } 391 392 func (c *float64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 393 return *((*float64)(p)) == 0 394 } 395 396 type boolCodec struct{} 397 398 func (c *boolCodec) Decode(_ context.Context, ptr unsafe.Pointer, iter *Iterator) { 399 if !iter.ReadNil() { 400 *((*bool)(ptr)) = iter.ReadBool() 401 } 402 } 403 404 func (c *boolCodec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 405 stream.WriteBool(*((*bool)(ptr))) 406 } 407 408 func (c *boolCodec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 409 return !(*((*bool)(p))) 410 } 411 412 type base64Codec struct { 413 sliceType *reflect2.UnsafeSliceType 414 sliceDecoder ValDecoder 415 } 416 417 func (c *base64Codec) Decode(ctx context.Context, ptr unsafe.Pointer, iter *Iterator) { 418 if iter.ReadNil() { 419 c.sliceType.UnsafeSetNil(ptr) 420 return 421 } 422 switch iter.WhatIsNext() { 423 case StringValue: 424 src := iter.ReadString() 425 dst, err := base64.StdEncoding.DecodeString(src) 426 if err != nil { 427 iter.ReportError("decode base64", err.Error()) 428 } else { 429 c.sliceType.UnsafeSet(ptr, unsafe.Pointer(&dst)) 430 } 431 case ArrayValue: 432 c.sliceDecoder.Decode(ctx, ptr, iter) 433 default: 434 iter.ReportError("base64Codec", "invalid input") 435 } 436 } 437 438 func (c *base64Codec) Encode(_ context.Context, ptr unsafe.Pointer, stream *Stream) { 439 if c.sliceType.UnsafeIsNil(ptr) { 440 stream.WriteNil() 441 return 442 } 443 src := *((*[]byte)(ptr)) 444 encoding := base64.StdEncoding 445 stream.writeByte('"') 446 if len(src) > 0 { 447 size := encoding.EncodedLen(len(src)) 448 buf := make([]byte, size) 449 encoding.Encode(buf, src) 450 stream.buf = append(stream.buf, buf...) 451 } 452 stream.writeByte('"') 453 } 454 455 func (c *base64Codec) IsEmpty(_ context.Context, p unsafe.Pointer, _ bool) bool { 456 return len(*((*[]byte)(p))) == 0 457 }