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