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  }