blob: 0d01374879a8d441492871fffe68fc576a103594 [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 "fmt"
7 "math"
8
9 "github.com/rcrowley/go-metrics"
10)
11
12type prepEncoder struct {
13 stack []pushEncoder
14 length int
15}
16
17// primitives
18
19func (pe *prepEncoder) putInt8(in int8) {
20 pe.length++
21}
22
23func (pe *prepEncoder) putInt16(in int16) {
24 pe.length += 2
25}
26
27func (pe *prepEncoder) putInt32(in int32) {
28 pe.length += 4
29}
30
31func (pe *prepEncoder) putInt64(in int64) {
32 pe.length += 8
33}
34
35func (pe *prepEncoder) putVarint(in int64) {
36 var buf [binary.MaxVarintLen64]byte
37 pe.length += binary.PutVarint(buf[:], in)
38}
39
khenaidood948f772021-08-11 17:49:24 -040040func (pe *prepEncoder) putUVarint(in uint64) {
41 var buf [binary.MaxVarintLen64]byte
42 pe.length += binary.PutUvarint(buf[:], in)
43}
44
khenaidooac637102019-01-14 15:44:34 -050045func (pe *prepEncoder) putArrayLength(in int) error {
46 if in > math.MaxInt32 {
47 return PacketEncodingError{fmt.Sprintf("array too long (%d)", in)}
48 }
49 pe.length += 4
50 return nil
51}
52
khenaidood948f772021-08-11 17:49:24 -040053func (pe *prepEncoder) putCompactArrayLength(in int) {
54 pe.putUVarint(uint64(in + 1))
55}
56
khenaidooac637102019-01-14 15:44:34 -050057func (pe *prepEncoder) putBool(in bool) {
58 pe.length++
59}
60
61// arrays
62
63func (pe *prepEncoder) putBytes(in []byte) error {
64 pe.length += 4
65 if in == nil {
66 return nil
67 }
68 return pe.putRawBytes(in)
69}
70
71func (pe *prepEncoder) putVarintBytes(in []byte) error {
72 if in == nil {
73 pe.putVarint(-1)
74 return nil
75 }
76 pe.putVarint(int64(len(in)))
77 return pe.putRawBytes(in)
78}
79
khenaidood948f772021-08-11 17:49:24 -040080func (pe *prepEncoder) putCompactBytes(in []byte) error {
81 pe.putUVarint(uint64(len(in) + 1))
82 return pe.putRawBytes(in)
83}
84
85func (pe *prepEncoder) putCompactString(in string) error {
86 pe.putCompactArrayLength(len(in))
87 return pe.putRawBytes([]byte(in))
88}
89
90func (pe *prepEncoder) putNullableCompactString(in *string) error {
91 if in == nil {
92 pe.putUVarint(0)
93 return nil
94 } else {
95 return pe.putCompactString(*in)
96 }
97}
98
khenaidooac637102019-01-14 15:44:34 -050099func (pe *prepEncoder) putRawBytes(in []byte) error {
100 if len(in) > math.MaxInt32 {
101 return PacketEncodingError{fmt.Sprintf("byteslice too long (%d)", len(in))}
102 }
103 pe.length += len(in)
104 return nil
105}
106
107func (pe *prepEncoder) putNullableString(in *string) error {
108 if in == nil {
109 pe.length += 2
110 return nil
111 }
112 return pe.putString(*in)
113}
114
115func (pe *prepEncoder) putString(in string) error {
116 pe.length += 2
117 if len(in) > math.MaxInt16 {
118 return PacketEncodingError{fmt.Sprintf("string too long (%d)", len(in))}
119 }
120 pe.length += len(in)
121 return nil
122}
123
124func (pe *prepEncoder) putStringArray(in []string) error {
125 err := pe.putArrayLength(len(in))
126 if err != nil {
127 return err
128 }
129
130 for _, str := range in {
131 if err := pe.putString(str); err != nil {
132 return err
133 }
134 }
135
136 return nil
137}
138
khenaidood948f772021-08-11 17:49:24 -0400139func (pe *prepEncoder) putCompactInt32Array(in []int32) error {
140 if in == nil {
141 return errors.New("expected int32 array to be non null")
142 }
143
144 pe.putUVarint(uint64(len(in)) + 1)
145 pe.length += 4 * len(in)
146 return nil
147}
148
149func (pe *prepEncoder) putNullableCompactInt32Array(in []int32) error {
150 if in == nil {
151 pe.putUVarint(0)
152 return nil
153 }
154
155 pe.putUVarint(uint64(len(in)) + 1)
156 pe.length += 4 * len(in)
157 return nil
158}
159
khenaidooac637102019-01-14 15:44:34 -0500160func (pe *prepEncoder) putInt32Array(in []int32) error {
161 err := pe.putArrayLength(len(in))
162 if err != nil {
163 return err
164 }
165 pe.length += 4 * len(in)
166 return nil
167}
168
169func (pe *prepEncoder) putInt64Array(in []int64) error {
170 err := pe.putArrayLength(len(in))
171 if err != nil {
172 return err
173 }
174 pe.length += 8 * len(in)
175 return nil
176}
177
khenaidood948f772021-08-11 17:49:24 -0400178func (pe *prepEncoder) putEmptyTaggedFieldArray() {
179 pe.putUVarint(0)
180}
181
khenaidooac637102019-01-14 15:44:34 -0500182func (pe *prepEncoder) offset() int {
183 return pe.length
184}
185
186// stackable
187
188func (pe *prepEncoder) push(in pushEncoder) {
189 in.saveOffset(pe.length)
190 pe.length += in.reserveLength()
191 pe.stack = append(pe.stack, in)
192}
193
194func (pe *prepEncoder) pop() error {
195 in := pe.stack[len(pe.stack)-1]
196 pe.stack = pe.stack[:len(pe.stack)-1]
197 if dpe, ok := in.(dynamicPushEncoder); ok {
198 pe.length += dpe.adjustLength(pe.length)
199 }
200
201 return nil
202}
203
204// we do not record metrics during the prep encoder pass
205func (pe *prepEncoder) metricRegistry() metrics.Registry {
206 return nil
207}