github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_decoder_native_array.go (about) 1 package jzon 2 3 import ( 4 "reflect" 5 "unsafe" 6 ) 7 8 type arrayDecoderBuilder struct { 9 decoder *arrayDecoder 10 elemPtrRType rtype 11 } 12 13 func newArrayDecoder(arrType reflect.Type) *arrayDecoderBuilder { 14 elem := arrType.Elem() 15 return &arrayDecoderBuilder{ 16 decoder: &arrayDecoder{ 17 rtype: rtypeOfType(arrType), 18 size: arrType.Size(), 19 elemSize: elem.Size(), 20 length: arrType.Len(), 21 // elemRType: rtypeOfType(elem), 22 }, 23 elemPtrRType: rtypeOfType(reflect.PtrTo(elem)), 24 } 25 } 26 27 func (builder *arrayDecoderBuilder) build(cache decoderCache) { 28 builder.decoder.elemDec = cache[builder.elemPtrRType] 29 } 30 31 type arrayDecoder struct { 32 rtype rtype 33 size uintptr 34 elemSize uintptr 35 length int 36 // elemRType rtype 37 38 elemDec ValDecoder 39 } 40 41 func (dec *arrayDecoder) Decode(ptr unsafe.Pointer, it *Iterator, _ *DecOpts) error { 42 c, err := it.nextToken() 43 if err != nil { 44 return err 45 } 46 if c == 'n' { 47 it.head++ 48 return it.expectBytes("ull") 49 } 50 if c != '[' { 51 return UnexpectedByteError{got: c, exp: '[', exp2: 'n'} 52 } 53 it.head++ 54 c, err = it.nextToken() 55 if err != nil { 56 return err 57 } 58 count := 0 59 var offset uintptr = 0 60 if c == ']' { 61 it.head++ 62 } else { 63 for { 64 if count < dec.length { 65 // newer golang version seems to disallow direct 66 // uintptr to unsafe.Pointer convert 67 elemPtr := add(ptr, offset, "count < dec.length") 68 if err := dec.elemDec.Decode(elemPtr, it, nil); err != nil { 69 return err 70 } 71 count++ 72 offset += dec.elemSize 73 } else { 74 if err := it.Skip(); err != nil { 75 return err 76 } 77 } 78 c, err = it.nextToken() 79 if err != nil { 80 return err 81 } 82 it.head++ 83 if c == ']' { 84 break 85 } 86 if c != ',' { 87 return UnexpectedByteError{got: c, exp: ']', exp2: ','} 88 } 89 } 90 } 91 if count < dec.length { 92 // should be safe (?) 93 typedmemclrpartial(dec.rtype, add(ptr, offset, "count < dec.length"), 94 offset, dec.size-offset) 95 } 96 return nil 97 }