github.com/hamba/avro/v2@v2.22.1-0.20240518180522-aff3955acf7d/codec.go (about)

     1  package avro
     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.CacheFingerprint(), 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  	rtype := typ.RType()
    68  	decoder := c.getDecoderFromCache(schema.CacheFingerprint(), rtype)
    69  	if decoder != nil {
    70  		return decoder
    71  	}
    72  
    73  	ptrType := typ.(*reflect2.UnsafePtrType)
    74  	decoder = decoderOfType(c, schema, ptrType.Elem())
    75  	c.addDecoderToCache(schema.CacheFingerprint(), rtype, decoder)
    76  	return decoder
    77  }
    78  
    79  func decoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValDecoder {
    80  	if dec := createDecoderOfMarshaler(cfg, schema, typ); dec != nil {
    81  		return dec
    82  	}
    83  
    84  	// Handle eface case when it isnt a union
    85  	if typ.Kind() == reflect.Interface && schema.Type() != Union {
    86  		if _, ok := typ.(*reflect2.UnsafeIFaceType); !ok {
    87  			return newEfaceDecoder(cfg, schema)
    88  		}
    89  	}
    90  
    91  	switch schema.Type() {
    92  	case String, Bytes, Int, Long, Float, Double, Boolean:
    93  		return createDecoderOfNative(schema.(*PrimitiveSchema), typ)
    94  
    95  	case Record:
    96  		return createDecoderOfRecord(cfg, schema, typ)
    97  
    98  	case Ref:
    99  		return decoderOfType(cfg, schema.(*RefSchema).Schema(), typ)
   100  
   101  	case Enum:
   102  		return createDecoderOfEnum(schema, typ)
   103  
   104  	case Array:
   105  		return createDecoderOfArray(cfg, schema, typ)
   106  
   107  	case Map:
   108  		return createDecoderOfMap(cfg, schema, typ)
   109  
   110  	case Union:
   111  		return createDecoderOfUnion(cfg, schema, typ)
   112  
   113  	case Fixed:
   114  		return createDecoderOfFixed(schema, typ)
   115  
   116  	default:
   117  		// It is impossible to get here with a valid schema
   118  		return &errorDecoder{err: fmt.Errorf("avro: schema type %s is unsupported", schema.Type())}
   119  	}
   120  }
   121  
   122  func (c *frozenConfig) EncoderOf(schema Schema, typ reflect2.Type) ValEncoder {
   123  	if typ == nil {
   124  		typ = reflect2.TypeOf((*null)(nil))
   125  	}
   126  
   127  	rtype := typ.RType()
   128  	encoder := c.getEncoderFromCache(schema.Fingerprint(), rtype)
   129  	if encoder != nil {
   130  		return encoder
   131  	}
   132  
   133  	encoder = encoderOfType(c, schema, typ)
   134  	if typ.LikePtr() {
   135  		encoder = &onePtrEncoder{encoder}
   136  	}
   137  	c.addEncoderToCache(schema.Fingerprint(), rtype, encoder)
   138  	return encoder
   139  }
   140  
   141  type onePtrEncoder struct {
   142  	enc ValEncoder
   143  }
   144  
   145  func (e *onePtrEncoder) Encode(ptr unsafe.Pointer, w *Writer) {
   146  	e.enc.Encode(noescape(unsafe.Pointer(&ptr)), w)
   147  }
   148  
   149  func encoderOfType(cfg *frozenConfig, schema Schema, typ reflect2.Type) ValEncoder {
   150  	if enc := createEncoderOfMarshaler(cfg, schema, typ); enc != nil {
   151  		return enc
   152  	}
   153  
   154  	if typ.Kind() == reflect.Interface {
   155  		return &interfaceEncoder{schema: schema, typ: typ}
   156  	}
   157  
   158  	switch schema.Type() {
   159  	case String, Bytes, Int, Long, Float, Double, Boolean, Null:
   160  		return createEncoderOfNative(schema, typ)
   161  
   162  	case Record:
   163  		return createEncoderOfRecord(cfg, schema, typ)
   164  
   165  	case Ref:
   166  		return encoderOfType(cfg, schema.(*RefSchema).Schema(), typ)
   167  
   168  	case Enum:
   169  		return createEncoderOfEnum(schema, typ)
   170  
   171  	case Array:
   172  		return createEncoderOfArray(cfg, schema, typ)
   173  
   174  	case Map:
   175  		return createEncoderOfMap(cfg, schema, typ)
   176  
   177  	case Union:
   178  		return createEncoderOfUnion(cfg, schema, typ)
   179  
   180  	case Fixed:
   181  		return createEncoderOfFixed(schema, typ)
   182  
   183  	default:
   184  		// It is impossible to get here with a valid schema
   185  		return &errorEncoder{err: fmt.Errorf("avro: schema type %s is unsupported", schema.Type())}
   186  	}
   187  }
   188  
   189  type errorDecoder struct {
   190  	err error
   191  }
   192  
   193  func (d *errorDecoder) Decode(_ unsafe.Pointer, r *Reader) {
   194  	if r.Error == nil {
   195  		r.Error = d.err
   196  	}
   197  }
   198  
   199  type errorEncoder struct {
   200  	err error
   201  }
   202  
   203  func (e *errorEncoder) Encode(_ unsafe.Pointer, w *Writer) {
   204  	if w.Error == nil {
   205  		w.Error = e.err
   206  	}
   207  }