github.com/hamba/avro@v1.8.0/codec_ptr.go (about)

     1  package avro
     2  
     3  import (
     4  	"errors"
     5  	"unsafe"
     6  
     7  	"github.com/modern-go/reflect2"
     8  )
     9  
    10  func decoderOfPtr(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
    11  	ptrType := typ.(*reflect2.UnsafePtrType)
    12  	elemType := ptrType.Elem()
    13  
    14  	decoder := decoderOfType(cfg, schema, elemType)
    15  
    16  	return &dereferenceDecoder{typ: elemType, decoder: decoder}
    17  }
    18  
    19  type dereferenceDecoder struct {
    20  	typ     reflect2.Type
    21  	decoder ValDecoder
    22  }
    23  
    24  func (d *dereferenceDecoder) Decode(ptr unsafe.Pointer, r *Reader) {
    25  	if *((*unsafe.Pointer)(ptr)) == nil {
    26  		// Create new instance
    27  		newPtr := d.typ.UnsafeNew()
    28  		d.decoder.Decode(newPtr, r)
    29  		*((*unsafe.Pointer)(ptr)) = newPtr
    30  		return
    31  	}
    32  
    33  	// Reuse existing instance
    34  	d.decoder.Decode(*((*unsafe.Pointer)(ptr)), r)
    35  }
    36  
    37  func encoderOfPtr(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
    38  	ptrType := typ.(*reflect2.UnsafePtrType)
    39  	elemType := ptrType.Elem()
    40  
    41  	enc := encoderOfType(cfg, schema, elemType)
    42  
    43  	return &dereferenceEncoder{typ: elemType, encoder: enc}
    44  }
    45  
    46  type dereferenceEncoder struct {
    47  	typ     reflect2.Type
    48  	encoder ValEncoder
    49  }
    50  
    51  func (d *dereferenceEncoder) Encode(ptr unsafe.Pointer, w *Writer) {
    52  	if *((*unsafe.Pointer)(ptr)) == nil {
    53  		w.Error = errors.New("avro: cannot encode nil pointer")
    54  		return
    55  	}
    56  
    57  	d.encoder.Encode(*((*unsafe.Pointer)(ptr)), w)
    58  }
    59  
    60  type referenceDecoder struct {
    61  	decoder ValDecoder
    62  }
    63  
    64  func (decoder *referenceDecoder) Decode(ptr unsafe.Pointer, r *Reader) {
    65  	decoder.decoder.Decode(unsafe.Pointer(&ptr), r)
    66  }