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  }