blob: b9bd17829b9902aba3c9bff6b2b5e9d97dada2f0 [file] [log] [blame]
Abhay Kumara2ae5992025-11-10 14:02:24 +00001package sarama
2
3import (
4 "encoding/binary"
5 "errors"
6 "math"
7 "time"
8
9 "github.com/rcrowley/go-metrics"
10)
11
12type realEncoder struct {
13 raw []byte
14 off int
15 stack []pushEncoder
16 registry metrics.Registry
17}
18
19type realFlexibleEncoder struct {
20 *realEncoder
21}
22
23// primitives
24
25func (re *realEncoder) putInt8(in int8) {
26 re.raw[re.off] = byte(in)
27 re.off++
28}
29
30func (re *realEncoder) putInt16(in int16) {
31 binary.BigEndian.PutUint16(re.raw[re.off:], uint16(in))
32 re.off += 2
33}
34
35func (re *realEncoder) putInt32(in int32) {
36 binary.BigEndian.PutUint32(re.raw[re.off:], uint32(in))
37 re.off += 4
38}
39
40func (re *realEncoder) putInt64(in int64) {
41 binary.BigEndian.PutUint64(re.raw[re.off:], uint64(in))
42 re.off += 8
43}
44
45func (re *realEncoder) putVarint(in int64) {
46 re.off += binary.PutVarint(re.raw[re.off:], in)
47}
48
49func (re *realEncoder) putUVarint(in uint64) {
50 re.off += binary.PutUvarint(re.raw[re.off:], in)
51}
52
53func (re *realEncoder) putFloat64(in float64) {
54 binary.BigEndian.PutUint64(re.raw[re.off:], math.Float64bits(in))
55 re.off += 8
56}
57
58func (re *realEncoder) putArrayLength(in int) error {
59 re.putInt32(int32(in))
60 return nil
61}
62
63func (re *realEncoder) putBool(in bool) {
64 if in {
65 re.putInt8(1)
66 return
67 }
68 re.putInt8(0)
69}
70
71func (re *realEncoder) putKError(in KError) {
72 re.putInt16(int16(in))
73}
74
75func (re *realEncoder) putDurationMs(in time.Duration) {
76 re.putInt32(int32(in / time.Millisecond))
77}
78
79// collection
80
81func (re *realEncoder) putRawBytes(in []byte) error {
82 copy(re.raw[re.off:], in)
83 re.off += len(in)
84 return nil
85}
86
87func (re *realEncoder) putBytes(in []byte) error {
88 if in == nil {
89 re.putInt32(-1)
90 return nil
91 }
92 re.putInt32(int32(len(in)))
93 return re.putRawBytes(in)
94}
95
96func (re *realEncoder) putVarintBytes(in []byte) error {
97 if in == nil {
98 re.putVarint(-1)
99 return nil
100 }
101 re.putVarint(int64(len(in)))
102 return re.putRawBytes(in)
103}
104
105func (re *realEncoder) putString(in string) error {
106 re.putInt16(int16(len(in)))
107 copy(re.raw[re.off:], in)
108 re.off += len(in)
109 return nil
110}
111
112func (re *realEncoder) putNullableString(in *string) error {
113 if in == nil {
114 re.putInt16(-1)
115 return nil
116 }
117 return re.putString(*in)
118}
119
120func (re *realEncoder) putStringArray(in []string) error {
121 err := re.putArrayLength(len(in))
122 if err != nil {
123 return err
124 }
125
126 for _, val := range in {
127 if err := re.putString(val); err != nil {
128 return err
129 }
130 }
131
132 return nil
133}
134
135func (re *realEncoder) putInt32Array(in []int32) error {
136 err := re.putArrayLength(len(in))
137 if err != nil {
138 return err
139 }
140 for _, val := range in {
141 re.putInt32(val)
142 }
143 return nil
144}
145
146func (re *realEncoder) putNullableInt32Array(in []int32) error {
147 if in == nil {
148 re.putInt32(-1)
149 return nil
150 }
151 err := re.putArrayLength(len(in))
152 if err != nil {
153 return err
154 }
155 for _, val := range in {
156 re.putInt32(val)
157 }
158 return nil
159}
160
161func (re *realEncoder) putInt64Array(in []int64) error {
162 err := re.putArrayLength(len(in))
163 if err != nil {
164 return err
165 }
166 for _, val := range in {
167 re.putInt64(val)
168 }
169 return nil
170}
171
172func (re *realEncoder) putEmptyTaggedFieldArray() {
173}
174
175func (re *realEncoder) offset() int {
176 return re.off
177}
178
179// stacks
180
181func (re *realEncoder) push(in pushEncoder) {
182 in.saveOffset(re.off)
183 re.off += in.reserveLength()
184 re.stack = append(re.stack, in)
185}
186
187func (re *realEncoder) pop() error {
188 // this is go's ugly pop pattern (the inverse of append)
189 in := re.stack[len(re.stack)-1]
190 re.stack = re.stack[:len(re.stack)-1]
191
192 return in.run(re.off, re.raw)
193}
194
195// we do record metrics during the real encoder pass
196func (re *realEncoder) metricRegistry() metrics.Registry {
197 return re.registry
198}
199
200func (re *realFlexibleEncoder) putArrayLength(in int) error {
201 // 0 represents a null array, so +1 has to be added
202 re.putUVarint(uint64(in + 1))
203 return nil
204}
205
206func (re *realFlexibleEncoder) putBytes(in []byte) error {
207 re.putUVarint(uint64(len(in) + 1))
208 return re.putRawBytes(in)
209}
210
211func (re *realFlexibleEncoder) putString(in string) error {
212 if err := re.putArrayLength(len(in)); err != nil {
213 return err
214 }
215 return re.putRawBytes([]byte(in))
216}
217
218func (re *realFlexibleEncoder) putNullableString(in *string) error {
219 if in == nil {
220 re.putInt8(0)
221 return nil
222 }
223 return re.putString(*in)
224}
225
226func (re *realFlexibleEncoder) putStringArray(in []string) error {
227 err := re.putArrayLength(len(in))
228 if err != nil {
229 return err
230 }
231
232 for _, val := range in {
233 if err := re.putString(val); err != nil {
234 return err
235 }
236 }
237
238 return nil
239}
240
241func (re *realFlexibleEncoder) putInt32Array(in []int32) error {
242 if in == nil {
243 return errors.New("expected int32 array to be non null")
244 }
245 // 0 represents a null array, so +1 has to be added
246 re.putUVarint(uint64(len(in)) + 1)
247 for _, val := range in {
248 re.putInt32(val)
249 }
250 return nil
251}
252
253func (re *realFlexibleEncoder) putNullableInt32Array(in []int32) error {
254 if in == nil {
255 re.putUVarint(0)
256 return nil
257 }
258 // 0 represents a null array, so +1 has to be added
259 re.putUVarint(uint64(len(in)) + 1)
260 for _, val := range in {
261 re.putInt32(val)
262 }
263 return nil
264}
265
266func (re *realFlexibleEncoder) putEmptyTaggedFieldArray() {
267 re.putUVarint(0)
268}