github.com/zerosnake0/jzon@v0.0.9-0.20230801092939-1b135cb83f7f/val_decoder_native_ptr.go (about) 1 package jzon 2 3 import ( 4 "reflect" 5 "unsafe" 6 ) 7 8 type pointerDecoderBuilder struct { 9 decoder *pointerDecoder 10 ptrRType rtype 11 } 12 13 func newPointerDecoder(typ reflect.Type) *pointerDecoderBuilder { 14 return &pointerDecoderBuilder{ 15 decoder: &pointerDecoder{ 16 elemRType: rtypeOfType(typ.Elem()), 17 }, 18 ptrRType: rtypeOfType(typ), 19 } 20 } 21 22 func (builder *pointerDecoderBuilder) build(cache decoderCache) { 23 builder.decoder.elemDec = cache[builder.ptrRType] 24 } 25 26 type pointerDecoder struct { 27 elemRType rtype 28 29 elemDec ValDecoder 30 } 31 32 func (dec *pointerDecoder) Decode(ptr unsafe.Pointer, it *Iterator, opts *DecOpts) error { 33 c, err := it.nextToken() 34 if err != nil { 35 return err 36 } 37 if c == 'n' { 38 it.head++ 39 if err = it.expectBytes("ull"); err != nil { 40 return err 41 } 42 *(*unsafe.Pointer)(ptr) = nil 43 } else { 44 elemPtr := *((*unsafe.Pointer)(ptr)) 45 var tgtPtr unsafe.Pointer 46 if elemPtr == nil { 47 tgtPtr = unsafe_New(dec.elemRType) 48 } else { 49 tgtPtr = elemPtr 50 } 51 if err = dec.elemDec.Decode(tgtPtr, it, opts); err != nil { 52 return err 53 } 54 if elemPtr == nil { 55 *(*unsafe.Pointer)(ptr) = tgtPtr 56 } 57 } 58 return nil 59 }