summaryrefslogtreecommitdiff
path: root/vendor/github.com/hamba/avro/v2/codec_generic.go
blob: 00ef1e20494fce49cf8294a46db0fb93ffce1fb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package avro

import (
	"errors"
	"math/big"
	"time"

	"github.com/modern-go/reflect2"
)

func genericDecode(typ reflect2.Type, dec ValDecoder, r *Reader) any {
	ptr := typ.UnsafeNew()
	dec.Decode(ptr, r)
	if r.Error != nil {
		return nil
	}

	obj := typ.UnsafeIndirect(ptr)
	if reflect2.IsNil(obj) {
		return nil
	}
	return obj
}

func genericReceiver(schema Schema) (reflect2.Type, error) {
	if schema.Type() == Ref {
		schema = schema.(*RefSchema).Schema()
	}

	var ls LogicalSchema
	lts, ok := schema.(LogicalTypeSchema)
	if ok {
		ls = lts.Logical()
	}

	schemaName := string(schema.Type())
	if ls != nil {
		schemaName += "." + string(ls.Type())
	}

	switch schema.Type() {
	case Null:
		return reflect2.TypeOf((*null)(nil)), nil
	case Boolean:
		var v bool
		return reflect2.TypeOf(v), nil
	case Int:
		if ls != nil {
			switch ls.Type() {
			case Date:
				var v time.Time
				return reflect2.TypeOf(v), nil

			case TimeMillis:
				var v time.Duration
				return reflect2.TypeOf(v), nil
			}
		}
		var v int
		return reflect2.TypeOf(v), nil
	case Long:
		if ls != nil {
			switch ls.Type() {
			case TimeMicros:
				var v time.Duration
				return reflect2.TypeOf(v), nil
			case TimestampMillis:
				var v time.Time
				return reflect2.TypeOf(v), nil
			case TimestampMicros:
				var v time.Time
				return reflect2.TypeOf(v), nil
			case LocalTimestampMillis:
				var v time.Time
				return reflect2.TypeOf(v), nil
			case LocalTimestampMicros:
				var v time.Time
				return reflect2.TypeOf(v), nil
			}
		}
		var v int64
		return reflect2.TypeOf(v), nil
	case Float:
		var v float32
		return reflect2.TypeOf(v), nil
	case Double:
		var v float64
		return reflect2.TypeOf(v), nil
	case String:
		var v string
		return reflect2.TypeOf(v), nil
	case Bytes:
		if ls != nil && ls.Type() == Decimal {
			var v *big.Rat
			return reflect2.TypeOf(v), nil
		}
		var v []byte
		return reflect2.TypeOf(v), nil
	case Record:
		var v map[string]any
		return reflect2.TypeOf(v), nil
	case Enum:
		var v string
		return reflect2.TypeOf(v), nil
	case Array:
		v := make([]any, 0)
		return reflect2.TypeOf(v), nil
	case Map:
		var v map[string]any
		return reflect2.TypeOf(v), nil
	case Union:
		var v map[string]any
		return reflect2.TypeOf(v), nil
	case Fixed:
		fixed := schema.(*FixedSchema)
		ls := fixed.Logical()
		if ls != nil {
			switch ls.Type() {
			case Duration:
				var v LogicalDuration
				return reflect2.TypeOf(v), nil
			case Decimal:
				var v *big.Rat
				return reflect2.TypeOf(v), nil
			}
		}
		v := byteSliceToArray(make([]byte, fixed.Size()), fixed.Size())
		return reflect2.TypeOf(v), nil
	default:
		// This should not be possible.
		return nil, errors.New("dynamic receiver not found for schema " + schemaName)
	}
}