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

     1  package avro
     2  
     3  import (
     4  	"errors"
     5  	"math/big"
     6  	"time"
     7  
     8  	"github.com/modern-go/reflect2"
     9  )
    10  
    11  func genericDecode(typ reflect2.Type, dec ValDecoder, r *Reader) any {
    12  	ptr := typ.UnsafeNew()
    13  	dec.Decode(ptr, r)
    14  	if r.Error != nil {
    15  		return nil
    16  	}
    17  
    18  	obj := typ.UnsafeIndirect(ptr)
    19  	if reflect2.IsNil(obj) {
    20  		return nil
    21  	}
    22  
    23  	// Generic reader returns a different result from the
    24  	// codec in the case of a big.Rat. Handle this.
    25  	if typ.Type1() == ratType {
    26  		dec := obj.(big.Rat)
    27  		return &dec
    28  	}
    29  	return obj
    30  }
    31  
    32  func genericReceiver(schema Schema) (reflect2.Type, error) {
    33  	if schema.Type() == Ref {
    34  		schema = schema.(*RefSchema).Schema()
    35  	}
    36  
    37  	var ls LogicalSchema
    38  	lts, ok := schema.(LogicalTypeSchema)
    39  	if ok {
    40  		ls = lts.Logical()
    41  	}
    42  
    43  	schemaName := string(schema.Type())
    44  	if ls != nil {
    45  		schemaName += "." + string(ls.Type())
    46  	}
    47  
    48  	switch schema.Type() {
    49  	case Boolean:
    50  		var v bool
    51  		return reflect2.TypeOf(v), nil
    52  	case Int:
    53  		if ls != nil {
    54  			switch ls.Type() {
    55  			case Date:
    56  				var v time.Time
    57  				return reflect2.TypeOf(v), nil
    58  
    59  			case TimeMillis:
    60  				var v time.Duration
    61  				return reflect2.TypeOf(v), nil
    62  			}
    63  		}
    64  		var v int
    65  		return reflect2.TypeOf(v), nil
    66  	case Long:
    67  		if ls != nil {
    68  			switch ls.Type() {
    69  			case TimeMicros:
    70  				var v time.Duration
    71  				return reflect2.TypeOf(v), nil
    72  			case TimestampMillis:
    73  				var v time.Time
    74  				return reflect2.TypeOf(v), nil
    75  			case TimestampMicros:
    76  				var v time.Time
    77  				return reflect2.TypeOf(v), nil
    78  			case LocalTimestampMillis:
    79  				var v time.Time
    80  				return reflect2.TypeOf(v), nil
    81  			case LocalTimestampMicros:
    82  				var v time.Time
    83  				return reflect2.TypeOf(v), nil
    84  			}
    85  		}
    86  		var v int64
    87  		return reflect2.TypeOf(v), nil
    88  	case Float:
    89  		var v float32
    90  		return reflect2.TypeOf(v), nil
    91  	case Double:
    92  		var v float64
    93  		return reflect2.TypeOf(v), nil
    94  	case String:
    95  		var v string
    96  		return reflect2.TypeOf(v), nil
    97  	case Bytes:
    98  		if ls != nil && ls.Type() == Decimal {
    99  			var v *big.Rat
   100  			return reflect2.TypeOf(v), nil
   101  		}
   102  		var v []byte
   103  		return reflect2.TypeOf(v), nil
   104  	case Record:
   105  		var v map[string]any
   106  		return reflect2.TypeOf(v), nil
   107  	case Enum:
   108  		var v string
   109  		return reflect2.TypeOf(v), nil
   110  	case Array:
   111  		v := make([]any, 0)
   112  		return reflect2.TypeOf(v), nil
   113  	case Map:
   114  		var v map[string]any
   115  		return reflect2.TypeOf(v), nil
   116  	case Union:
   117  		var v map[string]any
   118  		return reflect2.TypeOf(v), nil
   119  	case Fixed:
   120  		fixed := schema.(*FixedSchema)
   121  		ls := fixed.Logical()
   122  		if ls != nil {
   123  			switch ls.Type() {
   124  			case Duration:
   125  				var v LogicalDuration
   126  				return reflect2.TypeOf(v), nil
   127  			case Decimal:
   128  				var v big.Rat
   129  				return reflect2.TypeOf(v), nil
   130  			}
   131  		}
   132  		v := byteSliceToArray(make([]byte, fixed.Size()), fixed.Size())
   133  		return reflect2.TypeOf(v), nil
   134  	default:
   135  		// This should not be possible.
   136  		return nil, errors.New("dynamic receiver not found for schema " + schemaName)
   137  	}
   138  }