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 }