github.com/aacfactory/avro@v1.2.12/internal/base/codec_raw.go (about)

     1  package base
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/modern-go/reflect2"
     6  	"reflect"
     7  	"unsafe"
     8  )
     9  
    10  var (
    11  	marshalerType   = reflect2.TypeOfPtr((*Marshaler)(nil)).Elem()
    12  	unmarshalerType = reflect2.TypeOfPtr((*Unmarshaler)(nil)).Elem()
    13  )
    14  
    15  var (
    16  	rawSchema = NewPrimitiveSchema(Bytes, nil)
    17  )
    18  
    19  type Marshaler interface {
    20  	MarshalAvro() ([]byte, error)
    21  }
    22  
    23  type Unmarshaler interface {
    24  	UnmarshalAvro(p []byte) error
    25  }
    26  
    27  func createDecoderOfRaw(_ *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
    28  	if typ.Implements(unmarshalerType) && typ.Kind() == reflect.Ptr && schema.Type() == Raw {
    29  		return &rawCodec{
    30  			typ: typ,
    31  		}
    32  	}
    33  	ptrType := reflect2.PtrTo(typ)
    34  	if ptrType.Implements(unmarshalerType) && ptrType.Kind() == reflect.Ptr && schema.Type() == Raw {
    35  		return &referenceDecoder{
    36  			&rawCodec{ptrType},
    37  		}
    38  	}
    39  	return &errorDecoder{err: fmt.Errorf("avro: schema type %s is unsupported", schema.Type())}
    40  }
    41  
    42  func createEncoderOfRaw(_ *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
    43  	if typ.Implements(marshalerType) && schema.Type() == Raw {
    44  		return &rawCodec{
    45  			typ: typ,
    46  		}
    47  	}
    48  	return &errorEncoder{err: fmt.Errorf("avro: schema type %s is unsupported", schema.Type())}
    49  }
    50  
    51  type rawCodec struct {
    52  	typ reflect2.Type
    53  }
    54  
    55  func (c rawCodec) Decode(ptr unsafe.Pointer, r *Reader) {
    56  	obj := c.typ.UnsafeIndirect(ptr)
    57  	if reflect2.IsNil(obj) {
    58  		ptrType := c.typ.(*reflect2.UnsafePtrType)
    59  		newPtr := ptrType.Elem().UnsafeNew()
    60  		*((*unsafe.Pointer)(ptr)) = newPtr
    61  		obj = c.typ.UnsafeIndirect(ptr)
    62  	}
    63  	unmarshaler := (obj).(Unmarshaler)
    64  	b := r.ReadBytes()
    65  	p := make([]byte, 0)
    66  	decodeErr := Unmarshal(rawSchema, b, &p)
    67  	if decodeErr != nil {
    68  		r.ReportError("MarshalerCodec", decodeErr.Error())
    69  		return
    70  	}
    71  	err := unmarshaler.UnmarshalAvro(p)
    72  	if err != nil {
    73  		r.ReportError("MarshalerCodec", err.Error())
    74  	}
    75  }
    76  
    77  func (c rawCodec) Encode(ptr unsafe.Pointer, w *Writer) {
    78  	obj := c.typ.UnsafeIndirect(ptr)
    79  	if c.typ.IsNullable() && reflect2.IsNil(obj) {
    80  		w.WriteBytes(nil)
    81  		return
    82  	}
    83  	marshaler := (obj).(Marshaler)
    84  	b, err := marshaler.MarshalAvro()
    85  	if err != nil {
    86  		w.Error = err
    87  		return
    88  	}
    89  	b, err = Marshal(rawSchema, b)
    90  	if err != nil {
    91  		w.Error = err
    92  		return
    93  	}
    94  	w.WriteBytes(b)
    95  }