1use bytes::BufMut;
3
4use crate::{
5 DecodeBorrow, Encode, ProtocolError, UnknownTaggedFields,
6 owned::vote_request,
7 primitives::{
8 array::{array_len_prefix_len, get_array_len, put_array_len},
9 fixed::{get_bool, get_i32, get_i64, put_bool, put_i32, put_i64},
10 string_bytes::{
11 compact_nullable_string_len, compact_string_len, nullable_string_len,
12 put_compact_nullable_string, put_compact_string, put_nullable_string, put_string,
13 string_len,
14 },
15 string_bytes_borrowed::{
16 get_compact_nullable_string_borrowed, get_compact_string_borrowed,
17 get_nullable_string_borrowed, get_string_borrowed,
18 },
19 uuid::{Uuid, get_uuid, put_uuid},
20 },
21 tagged_fields::{WriteTaggedFields, read_tagged_fields, tagged_fields_len},
22};
23pub const API_KEY: i16 = 52;
24pub const MIN_VERSION: i16 = 0;
25pub const MAX_VERSION: i16 = 2;
26pub const LATEST_STABLE_VERSION: i16 = 2;
27pub const FLEXIBLE_MIN: i16 = 0;
28#[inline]
29#[must_use]
30pub fn is_flexible(version: i16) -> bool {
31 version >= FLEXIBLE_MIN
32}
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct VoteRequest<'a> {
35 pub cluster_id: Option<&'a str>,
36 pub voter_id: i32,
37 pub topics: Vec<TopicData<'a>>,
38 pub unknown_tagged_fields: UnknownTaggedFields,
39}
40impl Default for VoteRequest<'_> {
41 fn default() -> Self {
42 Self {
43 cluster_id: None,
44 voter_id: -1i32,
45 topics: Vec::new(),
46 unknown_tagged_fields: UnknownTaggedFields::default(),
47 }
48 }
49}
50impl VoteRequest<'_> {
51 #[must_use]
52 pub fn to_owned(&self) -> vote_request::VoteRequest {
53 vote_request::VoteRequest {
54 cluster_id: (self.cluster_id).map(str::to_owned),
55 voter_id: (self.voter_id),
56 topics: (self.topics).iter().map(TopicData::to_owned).collect(),
57 unknown_tagged_fields: self.unknown_tagged_fields.clone(),
58 }
59 }
60}
61impl Encode for VoteRequest<'_> {
62 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
63 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
64 return Err(ProtocolError::UnsupportedVersion {
65 api_key: API_KEY,
66 version,
67 });
68 }
69 let flex = is_flexible(version);
70 if version >= 0 {
71 if flex {
72 put_compact_nullable_string(buf, self.cluster_id)?;
73 } else {
74 put_nullable_string(buf, self.cluster_id)?;
75 }
76 }
77 if version >= 1 {
78 put_i32(buf, self.voter_id);
79 }
80 if version >= 0 {
81 {
82 put_array_len(buf, (self.topics).len(), flex)?;
83 for it in &self.topics {
84 it.encode(buf, version)?;
85 }
86 }
87 }
88 if flex {
89 let tagged = WriteTaggedFields::new();
90 tagged.write(buf, &self.unknown_tagged_fields)?;
91 }
92 Ok(())
93 }
94 fn encoded_len(&self, version: i16) -> usize {
95 let flex = is_flexible(version);
96 let mut n: usize = 0;
97 if version >= 0 {
98 n += if flex {
99 compact_nullable_string_len(self.cluster_id)
100 } else {
101 nullable_string_len(self.cluster_id)
102 };
103 }
104 if version >= 1 {
105 n += 4;
106 }
107 if version >= 0 {
108 n += {
109 let prefix = array_len_prefix_len((self.topics).len(), flex);
110 let body: usize = (self.topics).iter().map(|it| it.encoded_len(version)).sum();
111 prefix + body
112 };
113 }
114 if flex {
115 let known_pairs: Vec<(u32, usize)> = Vec::new();
116 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
117 }
118 n
119 }
120}
121impl<'de> DecodeBorrow<'de> for VoteRequest<'de> {
122 fn decode_borrow(buf: &mut &'de [u8], version: i16) -> Result<Self, ProtocolError> {
123 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
124 return Err(ProtocolError::UnsupportedVersion {
125 api_key: API_KEY,
126 version,
127 });
128 }
129 let flex = is_flexible(version);
130 let mut out = Self::default();
131 if version >= 0 {
132 out.cluster_id = if flex {
133 get_compact_nullable_string_borrowed(buf)?
134 } else {
135 get_nullable_string_borrowed(buf)?
136 };
137 }
138 if version >= 1 {
139 out.voter_id = get_i32(buf)?;
140 }
141 if version >= 0 {
142 out.topics = {
143 let n = get_array_len(buf, flex)?;
144 let mut v = Vec::with_capacity(n);
145 for _ in 0..n {
146 v.push(TopicData::decode_borrow(buf, version)?);
147 }
148 v
149 };
150 }
151 if flex {
152 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
153 }
154 Ok(out)
155 }
156}
157#[cfg(test)]
158impl VoteRequest<'_> {
159 #[must_use]
160 pub fn populated(version: i16) -> Self {
161 let mut m = Self::default();
162 if version >= 0 {
163 m.cluster_id = Some("x");
164 }
165 if version >= 1 {
166 m.voter_id = 1i32;
167 }
168 if version >= 0 {
169 m.topics = vec![TopicData::populated(version)];
170 }
171 m
172 }
173}
174#[derive(Debug, Clone, PartialEq, Eq, Default)]
175pub struct TopicData<'a> {
176 pub topic_name: &'a str,
177 pub partitions: Vec<PartitionData>,
178 pub unknown_tagged_fields: UnknownTaggedFields,
179}
180impl TopicData<'_> {
181 #[must_use]
182 pub fn to_owned(&self) -> vote_request::TopicData {
183 vote_request::TopicData {
184 topic_name: (self.topic_name).to_owned(),
185 partitions: (self.partitions)
186 .iter()
187 .map(PartitionData::to_owned)
188 .collect(),
189 unknown_tagged_fields: self.unknown_tagged_fields.clone(),
190 }
191 }
192}
193impl Encode for TopicData<'_> {
194 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
195 let flex = version >= 0;
196 if version >= 0 {
197 if flex {
198 put_compact_string(buf, self.topic_name)?;
199 } else {
200 put_string(buf, self.topic_name)?;
201 }
202 }
203 if version >= 0 {
204 {
205 put_array_len(buf, (self.partitions).len(), flex)?;
206 for it in &self.partitions {
207 it.encode(buf, version)?;
208 }
209 }
210 }
211 if flex {
212 let tagged = WriteTaggedFields::new();
213 tagged.write(buf, &self.unknown_tagged_fields)?;
214 }
215 Ok(())
216 }
217 fn encoded_len(&self, version: i16) -> usize {
218 let flex = version >= 0;
219 let mut n: usize = 0;
220 if version >= 0 {
221 n += if flex {
222 compact_string_len(self.topic_name)
223 } else {
224 string_len(self.topic_name)
225 };
226 }
227 if version >= 0 {
228 n += {
229 let prefix = array_len_prefix_len((self.partitions).len(), flex);
230 let body: usize = (self.partitions)
231 .iter()
232 .map(|it| it.encoded_len(version))
233 .sum();
234 prefix + body
235 };
236 }
237 if flex {
238 let known_pairs: Vec<(u32, usize)> = Vec::new();
239 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
240 }
241 n
242 }
243}
244impl<'de> DecodeBorrow<'de> for TopicData<'de> {
245 fn decode_borrow(buf: &mut &'de [u8], version: i16) -> Result<Self, ProtocolError> {
246 let flex = version >= 0;
247 let mut out = Self::default();
248 if version >= 0 {
249 out.topic_name = if flex {
250 get_compact_string_borrowed(buf)?
251 } else {
252 get_string_borrowed(buf)?
253 };
254 }
255 if version >= 0 {
256 out.partitions = {
257 let n = get_array_len(buf, flex)?;
258 let mut v = Vec::with_capacity(n);
259 for _ in 0..n {
260 v.push(PartitionData::decode_borrow(buf, version)?);
261 }
262 v
263 };
264 }
265 if flex {
266 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
267 }
268 Ok(out)
269 }
270}
271#[cfg(test)]
272impl TopicData<'_> {
273 #[must_use]
274 pub fn populated(version: i16) -> Self {
275 let mut m = Self::default();
276 if version >= 0 {
277 m.topic_name = "x";
278 }
279 if version >= 0 {
280 m.partitions = vec![PartitionData::populated(version)];
281 }
282 m
283 }
284}
285#[derive(Debug, Clone, PartialEq, Eq, Default)]
286pub struct PartitionData {
287 pub partition_index: i32,
288 pub replica_epoch: i32,
289 pub replica_id: i32,
290 pub replica_directory_id: Uuid,
291 pub voter_directory_id: Uuid,
292 pub last_offset_epoch: i32,
293 pub last_offset: i64,
294 pub pre_vote: bool,
295 pub unknown_tagged_fields: UnknownTaggedFields,
296}
297impl PartitionData {
298 #[must_use]
299 pub fn to_owned(&self) -> vote_request::PartitionData {
300 vote_request::PartitionData {
301 partition_index: (self.partition_index),
302 replica_epoch: (self.replica_epoch),
303 replica_id: (self.replica_id),
304 replica_directory_id: (self.replica_directory_id),
305 voter_directory_id: (self.voter_directory_id),
306 last_offset_epoch: (self.last_offset_epoch),
307 last_offset: (self.last_offset),
308 pre_vote: (self.pre_vote),
309 unknown_tagged_fields: self.unknown_tagged_fields.clone(),
310 }
311 }
312 fn encode_field_0<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
313 if version >= 0 {
314 put_i32(buf, self.partition_index);
315 }
316 }
317 fn encode_field_1<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
318 if version >= 0 {
319 put_i32(buf, self.replica_epoch);
320 }
321 }
322 fn encode_field_2<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
323 if version >= 0 {
324 put_i32(buf, self.replica_id);
325 }
326 }
327 fn encode_field_3<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
328 if version >= 1 {
329 put_uuid(buf, self.replica_directory_id);
330 }
331 }
332 fn encode_field_4<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
333 if version >= 1 {
334 put_uuid(buf, self.voter_directory_id);
335 }
336 }
337 fn encode_field_5<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
338 if version >= 0 {
339 put_i32(buf, self.last_offset_epoch);
340 }
341 }
342 fn encode_field_6<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
343 if version >= 0 {
344 put_i64(buf, self.last_offset);
345 }
346 }
347 fn encode_field_7<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
348 if version >= 2 {
349 put_bool(buf, self.pre_vote);
350 }
351 }
352 fn encode_tagged_fields<B: BufMut>(
353 &self,
354 buf: &mut B,
355 _version: i16,
356 flex: bool,
357 ) -> Result<(), ProtocolError> {
358 if flex {
359 let tagged = WriteTaggedFields::new();
360 tagged.write(buf, &self.unknown_tagged_fields)?;
361 }
362 Ok(())
363 }
364 fn decode_field_0(
365 out: &mut Self,
366 buf: &mut &[u8],
367 version: i16,
368 _flex: bool,
369 ) -> Result<(), ProtocolError> {
370 if version >= 0 {
371 out.partition_index = get_i32(buf)?;
372 }
373 Ok(())
374 }
375 fn decode_field_1(
376 out: &mut Self,
377 buf: &mut &[u8],
378 version: i16,
379 _flex: bool,
380 ) -> Result<(), ProtocolError> {
381 if version >= 0 {
382 out.replica_epoch = get_i32(buf)?;
383 }
384 Ok(())
385 }
386 fn decode_field_2(
387 out: &mut Self,
388 buf: &mut &[u8],
389 version: i16,
390 _flex: bool,
391 ) -> Result<(), ProtocolError> {
392 if version >= 0 {
393 out.replica_id = get_i32(buf)?;
394 }
395 Ok(())
396 }
397 fn decode_field_3(
398 out: &mut Self,
399 buf: &mut &[u8],
400 version: i16,
401 _flex: bool,
402 ) -> Result<(), ProtocolError> {
403 if version >= 1 {
404 out.replica_directory_id = get_uuid(buf)?;
405 }
406 Ok(())
407 }
408 fn decode_field_4(
409 out: &mut Self,
410 buf: &mut &[u8],
411 version: i16,
412 _flex: bool,
413 ) -> Result<(), ProtocolError> {
414 if version >= 1 {
415 out.voter_directory_id = get_uuid(buf)?;
416 }
417 Ok(())
418 }
419 fn decode_field_5(
420 out: &mut Self,
421 buf: &mut &[u8],
422 version: i16,
423 _flex: bool,
424 ) -> Result<(), ProtocolError> {
425 if version >= 0 {
426 out.last_offset_epoch = get_i32(buf)?;
427 }
428 Ok(())
429 }
430 fn decode_field_6(
431 out: &mut Self,
432 buf: &mut &[u8],
433 version: i16,
434 _flex: bool,
435 ) -> Result<(), ProtocolError> {
436 if version >= 0 {
437 out.last_offset = get_i64(buf)?;
438 }
439 Ok(())
440 }
441 fn decode_field_7(
442 out: &mut Self,
443 buf: &mut &[u8],
444 version: i16,
445 _flex: bool,
446 ) -> Result<(), ProtocolError> {
447 if version >= 2 {
448 out.pre_vote = get_bool(buf)?;
449 }
450 Ok(())
451 }
452 fn decode_tagged_fields(
453 out: &mut Self,
454 buf: &mut &[u8],
455 _version: i16,
456 flex: bool,
457 ) -> Result<(), ProtocolError> {
458 if flex {
459 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
460 }
461 Ok(())
462 }
463}
464impl Encode for PartitionData {
465 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
466 let flex = version >= 0;
467 self.encode_field_0(buf, version, flex);
468 self.encode_field_1(buf, version, flex);
469 self.encode_field_2(buf, version, flex);
470 self.encode_field_3(buf, version, flex);
471 self.encode_field_4(buf, version, flex);
472 self.encode_field_5(buf, version, flex);
473 self.encode_field_6(buf, version, flex);
474 self.encode_field_7(buf, version, flex);
475 self.encode_tagged_fields(buf, version, flex)?;
476 Ok(())
477 }
478 fn encoded_len(&self, version: i16) -> usize {
479 let flex = version >= 0;
480 let mut n: usize = 0;
481 if version >= 0 {
482 n += 4;
483 }
484 if version >= 0 {
485 n += 4;
486 }
487 if version >= 0 {
488 n += 4;
489 }
490 if version >= 1 {
491 n += 16;
492 }
493 if version >= 1 {
494 n += 16;
495 }
496 if version >= 0 {
497 n += 4;
498 }
499 if version >= 0 {
500 n += 8;
501 }
502 if version >= 2 {
503 n += 1;
504 }
505 if flex {
506 let known_pairs: Vec<(u32, usize)> = Vec::new();
507 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
508 }
509 n
510 }
511}
512impl<'de> DecodeBorrow<'de> for PartitionData {
513 fn decode_borrow(buf: &mut &'de [u8], version: i16) -> Result<Self, ProtocolError> {
514 let flex = version >= 0;
515 let mut out = Self::default();
516 Self::decode_field_0(&mut out, buf, version, flex)?;
517 Self::decode_field_1(&mut out, buf, version, flex)?;
518 Self::decode_field_2(&mut out, buf, version, flex)?;
519 Self::decode_field_3(&mut out, buf, version, flex)?;
520 Self::decode_field_4(&mut out, buf, version, flex)?;
521 Self::decode_field_5(&mut out, buf, version, flex)?;
522 Self::decode_field_6(&mut out, buf, version, flex)?;
523 Self::decode_field_7(&mut out, buf, version, flex)?;
524 Self::decode_tagged_fields(&mut out, buf, version, flex)?;
525 Ok(out)
526 }
527}
528#[cfg(test)]
529impl PartitionData {
530 #[must_use]
531 pub fn populated(version: i16) -> Self {
532 let mut m = Self::default();
533 if version >= 0 {
534 m.partition_index = 1i32;
535 }
536 if version >= 0 {
537 m.replica_epoch = 1i32;
538 }
539 if version >= 0 {
540 m.replica_id = 1i32;
541 }
542 if version >= 1 {
543 m.replica_directory_id = Uuid([1u8; 16]);
544 }
545 if version >= 1 {
546 m.voter_directory_id = Uuid([1u8; 16]);
547 }
548 if version >= 0 {
549 m.last_offset_epoch = 1i32;
550 }
551 if version >= 0 {
552 m.last_offset = 1i64;
553 }
554 if version >= 2 {
555 m.pre_vote = true;
556 }
557 m
558 }
559}