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 }