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 }