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