github.com/aacfactory/avro@v1.2.12/internal/base/codec.go (about) 1 package base 2 3 import ( 4 "fmt" 5 "math/big" 6 "reflect" 7 "time" 8 "unsafe" 9 10 "github.com/modern-go/reflect2" 11 ) 12 13 var ( 14 timeType = reflect.TypeOf(time.Time{}) 15 ratType = reflect.TypeOf(big.Rat{}) 16 durType = reflect.TypeOf(LogicalDuration{}) 17 ) 18 19 type null struct{} 20 21 // ValDecoder represents an internal value decoder. 22 // 23 // You should never use ValDecoder directly. 24 type ValDecoder interface { 25 Decode(ptr unsafe.Pointer, r *Reader) 26 } 27 28 // ValEncoder represents an internal value encoder. 29 // 30 // You should never use ValEncoder directly. 31 type ValEncoder interface { 32 Encode(ptr unsafe.Pointer, w *Writer) 33 } 34 35 // ReadVal parses Avro value and stores the result in the value pointed to by obj. 36 func (r *Reader) ReadVal(schema Schema, obj any) { 37 decoder := r.cfg.getDecoderFromCache(schema.Fingerprint(), reflect2.RTypeOf(obj)) 38 if decoder == nil { 39 typ := reflect2.TypeOf(obj) 40 if typ.Kind() != reflect.Ptr { 41 r.ReportError("ReadVal", "can only unmarshal into pointer") 42 return 43 } 44 decoder = r.cfg.DecoderOf(schema, typ) 45 } 46 47 ptr := reflect2.PtrOf(obj) 48 if ptr == nil { 49 r.ReportError("ReadVal", "can not read into nil pointer") 50 return 51 } 52 53 decoder.Decode(ptr, r) 54 } 55 56 // WriteVal writes the Avro encoding of obj. 57 func (w *Writer) WriteVal(schema Schema, val any) { 58 encoder := w.cfg.getEncoderFromCache(schema.Fingerprint(), reflect2.RTypeOf(val)) 59 if encoder == nil { 60 typ := reflect2.TypeOf(val) 61 encoder = w.cfg.EncoderOf(schema, typ) 62 } 63 encoder.Encode(reflect2.PtrOf(val), w) 64 } 65 66 func (c *frozenConfig) DecoderOf(schema Schema, typ reflect2.Type) ValDecoder { 67 processKey := c.borrowProcessDecoderGroupKey(schema, typ) 68 v, _, _ := c.processingGroup.Do(unsafe.String(unsafe.SliceData(processKey), len(processKey)), func() (interface{}, error) { 69 rtype := typ.RType() 70 decoder := c.getDecoderFromCache(schema.Fingerprint(), rtype) 71 if decoder != nil { 72 return decoder, nil 73 } 74 75 ptrType := typ.(*reflect2.UnsafePtrType) 76 decoder = decoderOfType(c, schema, ptrType.Elem()) 77 c.addDecoderToCache(schema.Fingerprint(), rtype, decoder) 78 return decoder, nil 79 }) 80 c.returnProcessGroupKey(processKey) 81 return v.(ValDecoder) 82 } 83 84 func decoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder { 85 if dec := createDecoderOfMarshaler(cfg, schema, typ); dec != nil { 86 return dec 87 } 88 89 if schema.Type() == Raw { 90 return createDecoderOfRaw(cfg, schema, typ) 91 } 92 93 // Handle eface case when it isnt a union 94 if typ.Kind() == reflect.Interface && schema.Type() != Union { 95 if _, ok := typ.(*reflect2.UnsafeIFaceType); !ok { 96 return &efaceDecoder{schema: schema} 97 } 98 } 99 100 switch schema.Type() { 101 case String, Bytes, Int, Long, Float, Double, Boolean: 102 return createDecoderOfNative(schema, typ) 103 104 case Record: 105 return createDecoderOfRecord(cfg, schema, typ) 106 107 case Ref: 108 return decoderOfType(cfg, schema.(*RefSchema).Schema(), typ) 109 110 case Enum: 111 return createDecoderOfEnum(schema, typ) 112 113 case Array: 114 return createDecoderOfArray(cfg, schema, typ) 115 116 case Map: 117 return createDecoderOfMap(cfg, schema, typ) 118 119 case Union: 120 return createDecoderOfUnion(cfg, schema, typ) 121 122 case Fixed: 123 return createDecoderOfFixed(schema, typ) 124 125 case Raw: 126 return createDecoderOfRaw(cfg, schema, typ) 127 default: 128 // It is impossible to get here with a valid schema 129 return &errorDecoder{err: fmt.Errorf("avro: schema type %s is unsupported", schema.Type())} 130 } 131 } 132 133 func (c *frozenConfig) EncoderOf(schema Schema, typ reflect2.Type) ValEncoder { 134 if typ == nil { 135 typ = reflect2.TypeOf((*null)(nil)) 136 } 137 138 processKey := c.borrowProcessEncoderGroupKey(schema, typ) 139 v, _, _ := c.processingGroup.Do(unsafe.String(unsafe.SliceData(processKey), len(processKey)), func() (interface{}, error) { 140 if typ == nil { 141 typ = reflect2.TypeOf((*null)(nil)) 142 } 143 144 rtype := typ.RType() 145 encoder := c.getEncoderFromCache(schema.Fingerprint(), rtype) 146 if encoder != nil { 147 return encoder, nil 148 } 149 150 encoder = encoderOfType(c, schema, typ) 151 if typ.LikePtr() { 152 encoder = &onePtrEncoder{encoder} 153 } 154 c.addEncoderToCache(schema.Fingerprint(), rtype, encoder) 155 return encoder, nil 156 }) 157 c.returnProcessGroupKey(processKey) 158 return v.(ValEncoder) 159 } 160 161 type onePtrEncoder struct { 162 enc ValEncoder 163 } 164 165 func (e *onePtrEncoder) Encode(ptr unsafe.Pointer, w *Writer) { 166 e.enc.Encode(noescape(unsafe.Pointer(&ptr)), w) 167 } 168 169 func encoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder { 170 if enc := createEncoderOfMarshaler(cfg, schema, typ); enc != nil { 171 return enc 172 } 173 174 if schema.Type() == Raw { 175 return createEncoderOfRaw(cfg, schema, typ) 176 } 177 178 if typ.Kind() == reflect.Interface { 179 return &interfaceEncoder{schema: schema, typ: typ} 180 } 181 182 switch schema.Type() { 183 case String, Bytes, Int, Long, Float, Double, Boolean, Null: 184 return createEncoderOfNative(schema, typ) 185 186 case Record: 187 return createEncoderOfRecord(cfg, schema, typ) 188 189 case Ref: 190 return encoderOfType(cfg, schema.(*RefSchema).Schema(), typ) 191 192 case Enum: 193 return createEncoderOfEnum(schema, typ) 194 195 case Array: 196 return createEncoderOfArray(cfg, schema, typ) 197 198 case Map: 199 return createEncoderOfMap(cfg, schema, typ) 200 201 case Union: 202 return createEncoderOfUnion(cfg, schema, typ) 203 204 case Fixed: 205 return createEncoderOfFixed(schema, typ) 206 case Raw: 207 return createEncoderOfRaw(cfg, schema, typ) 208 default: 209 // It is impossible to get here with a valid schema 210 return &errorEncoder{err: fmt.Errorf("avro: schema type %s is unsupported", schema.Type())} 211 } 212 } 213 214 type errorDecoder struct { 215 err error 216 } 217 218 func (d *errorDecoder) Decode(_ unsafe.Pointer, r *Reader) { 219 if r.Error == nil { 220 r.Error = d.err 221 } 222 } 223 224 type errorEncoder struct { 225 err error 226 } 227 228 func (e *errorEncoder) Encode(_ unsafe.Pointer, w *Writer) { 229 if w.Error == nil { 230 w.Error = e.err 231 } 232 }