blob: d6a0ddf1247645f9d0df522da170adfbffb1aa34 [file] [log] [blame]
kesavand2cde6582020-06-22 04:56:23 -04001package sarama
2
3import (
4 "encoding/binary"
kesavandc71914f2022-03-25 11:19:03 +05305 "errors"
6 "math"
kesavand2cde6582020-06-22 04:56:23 -04007
8 "github.com/rcrowley/go-metrics"
9)
10
11type realEncoder struct {
12 raw []byte
13 off int
14 stack []pushEncoder
15 registry metrics.Registry
16}
17
18// primitives
19
20func (re *realEncoder) putInt8(in int8) {
21 re.raw[re.off] = byte(in)
22 re.off++
23}
24
25func (re *realEncoder) putInt16(in int16) {
26 binary.BigEndian.PutUint16(re.raw[re.off:], uint16(in))
27 re.off += 2
28}
29
30func (re *realEncoder) putInt32(in int32) {
31 binary.BigEndian.PutUint32(re.raw[re.off:], uint32(in))
32 re.off += 4
33}
34
35func (re *realEncoder) putInt64(in int64) {
36 binary.BigEndian.PutUint64(re.raw[re.off:], uint64(in))
37 re.off += 8
38}
39
40func (re *realEncoder) putVarint(in int64) {
41 re.off += binary.PutVarint(re.raw[re.off:], in)
42}
43
kesavandc71914f2022-03-25 11:19:03 +053044func (re *realEncoder) putUVarint(in uint64) {
45 re.off += binary.PutUvarint(re.raw[re.off:], in)
46}
47
48func (re *realEncoder) putFloat64(in float64) {
49 binary.BigEndian.PutUint64(re.raw[re.off:], math.Float64bits(in))
50 re.off += 8
51}
52
kesavand2cde6582020-06-22 04:56:23 -040053func (re *realEncoder) putArrayLength(in int) error {
54 re.putInt32(int32(in))
55 return nil
56}
57
kesavandc71914f2022-03-25 11:19:03 +053058func (re *realEncoder) putCompactArrayLength(in int) {
59 // 0 represents a null array, so +1 has to be added
60 re.putUVarint(uint64(in + 1))
61}
62
kesavand2cde6582020-06-22 04:56:23 -040063func (re *realEncoder) putBool(in bool) {
64 if in {
65 re.putInt8(1)
66 return
67 }
68 re.putInt8(0)
69}
70
71// collection
72
73func (re *realEncoder) putRawBytes(in []byte) error {
74 copy(re.raw[re.off:], in)
75 re.off += len(in)
76 return nil
77}
78
79func (re *realEncoder) putBytes(in []byte) error {
80 if in == nil {
81 re.putInt32(-1)
82 return nil
83 }
84 re.putInt32(int32(len(in)))
85 return re.putRawBytes(in)
86}
87
88func (re *realEncoder) putVarintBytes(in []byte) error {
89 if in == nil {
90 re.putVarint(-1)
91 return nil
92 }
93 re.putVarint(int64(len(in)))
94 return re.putRawBytes(in)
95}
96
kesavandc71914f2022-03-25 11:19:03 +053097func (re *realEncoder) putCompactBytes(in []byte) error {
98 re.putUVarint(uint64(len(in) + 1))
99 return re.putRawBytes(in)
100}
101
102func (re *realEncoder) putCompactString(in string) error {
103 re.putCompactArrayLength(len(in))
104 return re.putRawBytes([]byte(in))
105}
106
107func (re *realEncoder) putNullableCompactString(in *string) error {
108 if in == nil {
109 re.putInt8(0)
110 return nil
111 }
112 return re.putCompactString(*in)
113}
114
kesavand2cde6582020-06-22 04:56:23 -0400115func (re *realEncoder) putString(in string) error {
116 re.putInt16(int16(len(in)))
117 copy(re.raw[re.off:], in)
118 re.off += len(in)
119 return nil
120}
121
122func (re *realEncoder) putNullableString(in *string) error {
123 if in == nil {
124 re.putInt16(-1)
125 return nil
126 }
127 return re.putString(*in)
128}
129
130func (re *realEncoder) putStringArray(in []string) error {
131 err := re.putArrayLength(len(in))
132 if err != nil {
133 return err
134 }
135
136 for _, val := range in {
137 if err := re.putString(val); err != nil {
138 return err
139 }
140 }
141
142 return nil
143}
144
kesavandc71914f2022-03-25 11:19:03 +0530145func (re *realEncoder) putCompactInt32Array(in []int32) error {
146 if in == nil {
147 return errors.New("expected int32 array to be non null")
148 }
149 // 0 represents a null array, so +1 has to be added
150 re.putUVarint(uint64(len(in)) + 1)
151 for _, val := range in {
152 re.putInt32(val)
153 }
154 return nil
155}
156
157func (re *realEncoder) putNullableCompactInt32Array(in []int32) error {
158 if in == nil {
159 re.putUVarint(0)
160 return nil
161 }
162 // 0 represents a null array, so +1 has to be added
163 re.putUVarint(uint64(len(in)) + 1)
164 for _, val := range in {
165 re.putInt32(val)
166 }
167 return nil
168}
169
kesavand2cde6582020-06-22 04:56:23 -0400170func (re *realEncoder) putInt32Array(in []int32) error {
171 err := re.putArrayLength(len(in))
172 if err != nil {
173 return err
174 }
175 for _, val := range in {
176 re.putInt32(val)
177 }
178 return nil
179}
180
181func (re *realEncoder) putInt64Array(in []int64) error {
182 err := re.putArrayLength(len(in))
183 if err != nil {
184 return err
185 }
186 for _, val := range in {
187 re.putInt64(val)
188 }
189 return nil
190}
191
kesavandc71914f2022-03-25 11:19:03 +0530192func (re *realEncoder) putEmptyTaggedFieldArray() {
193 re.putUVarint(0)
194}
195
kesavand2cde6582020-06-22 04:56:23 -0400196func (re *realEncoder) offset() int {
197 return re.off
198}
199
200// stacks
201
202func (re *realEncoder) push(in pushEncoder) {
203 in.saveOffset(re.off)
204 re.off += in.reserveLength()
205 re.stack = append(re.stack, in)
206}
207
208func (re *realEncoder) pop() error {
209 // this is go's ugly pop pattern (the inverse of append)
210 in := re.stack[len(re.stack)-1]
211 re.stack = re.stack[:len(re.stack)-1]
212
213 return in.run(re.off, re.raw)
214}
215
216// we do record metrics during the real encoder pass
217func (re *realEncoder) metricRegistry() metrics.Registry {
218 return re.registry
219}