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

     1  package base
     2  
     3  import (
     4  	"encoding"
     5  	"unsafe"
     6  
     7  	"github.com/modern-go/reflect2"
     8  )
     9  
    10  var (
    11  	textMarshalerType   = reflect2.TypeOfPtr((*encoding.TextMarshaler)(nil)).Elem()
    12  	textUnmarshalerType = reflect2.TypeOfPtr((*encoding.TextUnmarshaler)(nil)).Elem()
    13  )
    14  
    15  func createDecoderOfMarshaler(_ *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
    16  	if typ.Implements(textUnmarshalerType) && schema.Type() == String {
    17  		return &textMarshalerCodec{typ}
    18  	}
    19  	ptrType := reflect2.PtrTo(typ)
    20  	if ptrType.Implements(textUnmarshalerType) && schema.Type() == String {
    21  		return &referenceDecoder{
    22  			&textMarshalerCodec{ptrType},
    23  		}
    24  	}
    25  	return nil
    26  }
    27  
    28  func createEncoderOfMarshaler(_ *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
    29  	if typ.Implements(textMarshalerType) && schema.Type() == String {
    30  		return &textMarshalerCodec{
    31  			typ: typ,
    32  		}
    33  	}
    34  	return nil
    35  }
    36  
    37  type textMarshalerCodec struct {
    38  	typ reflect2.Type
    39  }
    40  
    41  func (c textMarshalerCodec) Decode(ptr unsafe.Pointer, r *Reader) {
    42  	obj := c.typ.UnsafeIndirect(ptr)
    43  	if reflect2.IsNil(obj) {
    44  		ptrType := c.typ.(*reflect2.UnsafePtrType)
    45  		newPtr := ptrType.Elem().UnsafeNew()
    46  		*((*unsafe.Pointer)(ptr)) = newPtr
    47  		obj = c.typ.UnsafeIndirect(ptr)
    48  	}
    49  	unmarshaler := (obj).(encoding.TextUnmarshaler)
    50  	b := r.ReadBytes()
    51  	if len(b) == 0 {
    52  		return
    53  	}
    54  	err := unmarshaler.UnmarshalText(b)
    55  	if err != nil {
    56  		r.ReportError("textMarshalerCodec", err.Error())
    57  	}
    58  }
    59  
    60  func (c textMarshalerCodec) Encode(ptr unsafe.Pointer, w *Writer) {
    61  	obj := c.typ.UnsafeIndirect(ptr)
    62  	if c.typ.IsNullable() && reflect2.IsNil(obj) {
    63  		w.WriteBytes(nil)
    64  		return
    65  	}
    66  	marshaler := (obj).(encoding.TextMarshaler)
    67  	b, err := marshaler.MarshalText()
    68  	if err != nil {
    69  		w.Error = err
    70  		return
    71  	}
    72  	w.WriteBytes(b)
    73  }