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  }