github.com/night-codes/go-json@v0.9.15/internal/decoder/ptr.go (about) 1 package decoder 2 3 import ( 4 "unsafe" 5 6 "github.com/night-codes/go-json/internal/runtime" 7 ) 8 9 type ptrDecoder struct { 10 dec Decoder 11 typ *runtime.Type 12 structName string 13 fieldName string 14 } 15 16 func newPtrDecoder(dec Decoder, typ *runtime.Type, structName, fieldName string) *ptrDecoder { 17 return &ptrDecoder{ 18 dec: dec, 19 typ: typ, 20 structName: structName, 21 fieldName: fieldName, 22 } 23 } 24 25 func (d *ptrDecoder) contentDecoder() Decoder { 26 dec, ok := d.dec.(*ptrDecoder) 27 if !ok { 28 return d.dec 29 } 30 return dec.contentDecoder() 31 } 32 33 //nolint:golint 34 //go:linkname unsafe_New reflect.unsafe_New 35 func unsafe_New(*runtime.Type) unsafe.Pointer 36 37 func (d *ptrDecoder) DecodeStream(s *Stream, depth int64, p unsafe.Pointer) error { 38 if s.skipWhiteSpace() == nul { 39 s.read() 40 } 41 if s.char() == 'n' { 42 if err := nullBytes(s); err != nil { 43 return err 44 } 45 *(*unsafe.Pointer)(p) = nil 46 return nil 47 } 48 var newptr unsafe.Pointer 49 if *(*unsafe.Pointer)(p) == nil { 50 newptr = unsafe_New(d.typ) 51 *(*unsafe.Pointer)(p) = newptr 52 } else { 53 newptr = *(*unsafe.Pointer)(p) 54 } 55 if err := d.dec.DecodeStream(s, depth, newptr); err != nil { 56 return err 57 } 58 return nil 59 } 60 61 func (d *ptrDecoder) Decode(ctx *RuntimeContext, cursor, depth int64, p unsafe.Pointer) (int64, error) { 62 buf := ctx.Buf 63 cursor = skipWhiteSpace(buf, cursor) 64 if buf[cursor] == 'n' { 65 if err := validateNull(buf, cursor); err != nil { 66 return 0, err 67 } 68 if p != nil { 69 *(*unsafe.Pointer)(p) = nil 70 } 71 cursor += 4 72 return cursor, nil 73 } 74 var newptr unsafe.Pointer 75 if *(*unsafe.Pointer)(p) == nil { 76 newptr = unsafe_New(d.typ) 77 *(*unsafe.Pointer)(p) = newptr 78 } else { 79 newptr = *(*unsafe.Pointer)(p) 80 } 81 c, err := d.dec.Decode(ctx, cursor, depth, newptr) 82 if err != nil { 83 return 0, err 84 } 85 cursor = c 86 return cursor, nil 87 }