1use bytes::BufMut;
3
4use crate::{
5 DecodeBorrow, Encode, ProtocolError, UnknownTaggedFields,
6 owned::txn_offset_commit_request,
7 primitives::{
8 array::{array_len_prefix_len, get_array_len, put_array_len},
9 fixed::{get_i16, get_i32, get_i64, put_i16, 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 = 28;
24pub const MIN_VERSION: i16 = 0;
25pub const MAX_VERSION: i16 = 6;
26pub const LATEST_STABLE_VERSION: i16 = 6;
27pub const FLEXIBLE_MIN: i16 = 3;
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 TxnOffsetCommitRequest<'a> {
35 pub transactional_id: &'a str,
36 pub group_id: &'a str,
37 pub producer_id: i64,
38 pub producer_epoch: i16,
39 pub generation_id_or_member_epoch: i32,
40 pub member_id: &'a str,
41 pub group_instance_id: Option<&'a str>,
42 pub topics: Vec<TxnOffsetCommitRequestTopic<'a>>,
43 pub unknown_tagged_fields: UnknownTaggedFields,
44}
45impl Default for TxnOffsetCommitRequest<'_> {
46 fn default() -> Self {
47 Self {
48 transactional_id: "",
49 group_id: "",
50 producer_id: 0i64,
51 producer_epoch: 0i16,
52 generation_id_or_member_epoch: -1i32,
53 member_id: "",
54 group_instance_id: None,
55 topics: Vec::new(),
56 unknown_tagged_fields: UnknownTaggedFields::default(),
57 }
58 }
59}
60impl<'a> TxnOffsetCommitRequest<'a> {
61 #[must_use]
62 pub fn to_owned(&self) -> txn_offset_commit_request::TxnOffsetCommitRequest {
63 txn_offset_commit_request::TxnOffsetCommitRequest {
64 transactional_id: (self.transactional_id).to_owned(),
65 group_id: (self.group_id).to_owned(),
66 producer_id: (self.producer_id),
67 producer_epoch: (self.producer_epoch),
68 generation_id_or_member_epoch: (self.generation_id_or_member_epoch),
69 member_id: (self.member_id).to_owned(),
70 group_instance_id: (self.group_instance_id).map(str::to_owned),
71 topics: (self.topics)
72 .iter()
73 .map(TxnOffsetCommitRequestTopic::to_owned)
74 .collect(),
75 unknown_tagged_fields: self.unknown_tagged_fields.clone(),
76 }
77 }
78 fn encode_field_0<B: BufMut>(
79 &self,
80 buf: &mut B,
81 version: i16,
82 flex: bool,
83 ) -> Result<(), ProtocolError> {
84 if version >= 0 {
85 if flex {
86 put_compact_string(buf, self.transactional_id)?;
87 } else {
88 put_string(buf, self.transactional_id)?;
89 }
90 }
91 Ok(())
92 }
93 fn encode_field_1<B: BufMut>(
94 &self,
95 buf: &mut B,
96 version: i16,
97 flex: bool,
98 ) -> Result<(), ProtocolError> {
99 if version >= 0 {
100 if flex {
101 put_compact_string(buf, self.group_id)?;
102 } else {
103 put_string(buf, self.group_id)?;
104 }
105 }
106 Ok(())
107 }
108 fn encode_field_2<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
109 if version >= 0 {
110 put_i64(buf, self.producer_id);
111 }
112 }
113 fn encode_field_3<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
114 if version >= 0 {
115 put_i16(buf, self.producer_epoch);
116 }
117 }
118 fn encode_field_4<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
119 if version >= 3 {
120 put_i32(buf, self.generation_id_or_member_epoch);
121 }
122 }
123 fn encode_field_5<B: BufMut>(
124 &self,
125 buf: &mut B,
126 version: i16,
127 flex: bool,
128 ) -> Result<(), ProtocolError> {
129 if version >= 3 {
130 if flex {
131 put_compact_string(buf, self.member_id)?;
132 } else {
133 put_string(buf, self.member_id)?;
134 }
135 }
136 Ok(())
137 }
138 fn encode_field_6<B: BufMut>(
139 &self,
140 buf: &mut B,
141 version: i16,
142 flex: bool,
143 ) -> Result<(), ProtocolError> {
144 if version >= 3 {
145 if flex {
146 put_compact_nullable_string(buf, self.group_instance_id)?;
147 } else {
148 put_nullable_string(buf, self.group_instance_id)?;
149 }
150 }
151 Ok(())
152 }
153 fn encode_field_7<B: BufMut>(
154 &self,
155 buf: &mut B,
156 version: i16,
157 flex: bool,
158 ) -> Result<(), ProtocolError> {
159 if version >= 0 {
160 {
161 put_array_len(buf, (self.topics).len(), flex)?;
162 for it in &self.topics {
163 it.encode(buf, version)?;
164 }
165 }
166 }
167 Ok(())
168 }
169 fn encode_tagged_fields<B: BufMut>(
170 &self,
171 buf: &mut B,
172 _version: i16,
173 flex: bool,
174 ) -> Result<(), ProtocolError> {
175 if flex {
176 let tagged = WriteTaggedFields::new();
177 tagged.write(buf, &self.unknown_tagged_fields)?;
178 }
179 Ok(())
180 }
181 fn decode_field_0(
182 out: &mut Self,
183 buf: &mut &'a [u8],
184 version: i16,
185 flex: bool,
186 ) -> Result<(), ProtocolError> {
187 if version >= 0 {
188 out.transactional_id = if flex {
189 get_compact_string_borrowed(buf)?
190 } else {
191 get_string_borrowed(buf)?
192 };
193 }
194 Ok(())
195 }
196 fn decode_field_1(
197 out: &mut Self,
198 buf: &mut &'a [u8],
199 version: i16,
200 flex: bool,
201 ) -> Result<(), ProtocolError> {
202 if version >= 0 {
203 out.group_id = if flex {
204 get_compact_string_borrowed(buf)?
205 } else {
206 get_string_borrowed(buf)?
207 };
208 }
209 Ok(())
210 }
211 fn decode_field_2(
212 out: &mut Self,
213 buf: &mut &'a [u8],
214 version: i16,
215 _flex: bool,
216 ) -> Result<(), ProtocolError> {
217 if version >= 0 {
218 out.producer_id = get_i64(buf)?;
219 }
220 Ok(())
221 }
222 fn decode_field_3(
223 out: &mut Self,
224 buf: &mut &'a [u8],
225 version: i16,
226 _flex: bool,
227 ) -> Result<(), ProtocolError> {
228 if version >= 0 {
229 out.producer_epoch = get_i16(buf)?;
230 }
231 Ok(())
232 }
233 fn decode_field_4(
234 out: &mut Self,
235 buf: &mut &'a [u8],
236 version: i16,
237 _flex: bool,
238 ) -> Result<(), ProtocolError> {
239 if version >= 3 {
240 out.generation_id_or_member_epoch = get_i32(buf)?;
241 }
242 Ok(())
243 }
244 fn decode_field_5(
245 out: &mut Self,
246 buf: &mut &'a [u8],
247 version: i16,
248 flex: bool,
249 ) -> Result<(), ProtocolError> {
250 if version >= 3 {
251 out.member_id = if flex {
252 get_compact_string_borrowed(buf)?
253 } else {
254 get_string_borrowed(buf)?
255 };
256 }
257 Ok(())
258 }
259 fn decode_field_6(
260 out: &mut Self,
261 buf: &mut &'a [u8],
262 version: i16,
263 flex: bool,
264 ) -> Result<(), ProtocolError> {
265 if version >= 3 {
266 out.group_instance_id = if flex {
267 get_compact_nullable_string_borrowed(buf)?
268 } else {
269 get_nullable_string_borrowed(buf)?
270 };
271 }
272 Ok(())
273 }
274 fn decode_field_7(
275 out: &mut Self,
276 buf: &mut &'a [u8],
277 version: i16,
278 flex: bool,
279 ) -> Result<(), ProtocolError> {
280 if version >= 0 {
281 out.topics = {
282 let n = get_array_len(buf, flex)?;
283 let mut v = Vec::with_capacity(n);
284 for _ in 0..n {
285 v.push(TxnOffsetCommitRequestTopic::decode_borrow(buf, version)?);
286 }
287 v
288 };
289 }
290 Ok(())
291 }
292 fn decode_tagged_fields(
293 out: &mut Self,
294 buf: &mut &'a [u8],
295 _version: i16,
296 flex: bool,
297 ) -> Result<(), ProtocolError> {
298 if flex {
299 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
300 }
301 Ok(())
302 }
303}
304impl Encode for TxnOffsetCommitRequest<'_> {
305 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
306 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
307 return Err(ProtocolError::UnsupportedVersion {
308 api_key: API_KEY,
309 version,
310 });
311 }
312 let flex = is_flexible(version);
313 self.encode_field_0(buf, version, flex)?;
314 self.encode_field_1(buf, version, flex)?;
315 self.encode_field_2(buf, version, flex);
316 self.encode_field_3(buf, version, flex);
317 self.encode_field_4(buf, version, flex);
318 self.encode_field_5(buf, version, flex)?;
319 self.encode_field_6(buf, version, flex)?;
320 self.encode_field_7(buf, version, flex)?;
321 self.encode_tagged_fields(buf, version, flex)?;
322 Ok(())
323 }
324 fn encoded_len(&self, version: i16) -> usize {
325 let flex = is_flexible(version);
326 let mut n: usize = 0;
327 if version >= 0 {
328 n += if flex {
329 compact_string_len(self.transactional_id)
330 } else {
331 string_len(self.transactional_id)
332 };
333 }
334 if version >= 0 {
335 n += if flex {
336 compact_string_len(self.group_id)
337 } else {
338 string_len(self.group_id)
339 };
340 }
341 if version >= 0 {
342 n += 8;
343 }
344 if version >= 0 {
345 n += 2;
346 }
347 if version >= 3 {
348 n += 4;
349 }
350 if version >= 3 {
351 n += if flex {
352 compact_string_len(self.member_id)
353 } else {
354 string_len(self.member_id)
355 };
356 }
357 if version >= 3 {
358 n += if flex {
359 compact_nullable_string_len(self.group_instance_id)
360 } else {
361 nullable_string_len(self.group_instance_id)
362 };
363 }
364 if version >= 0 {
365 n += {
366 let prefix = array_len_prefix_len((self.topics).len(), flex);
367 let body: usize = (self.topics).iter().map(|it| it.encoded_len(version)).sum();
368 prefix + body
369 };
370 }
371 if flex {
372 let known_pairs: Vec<(u32, usize)> = Vec::new();
373 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
374 }
375 n
376 }
377}
378impl<'de> DecodeBorrow<'de> for TxnOffsetCommitRequest<'de> {
379 fn decode_borrow(buf: &mut &'de [u8], version: i16) -> Result<Self, ProtocolError> {
380 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
381 return Err(ProtocolError::UnsupportedVersion {
382 api_key: API_KEY,
383 version,
384 });
385 }
386 let flex = is_flexible(version);
387 let mut out = Self::default();
388 Self::decode_field_0(&mut out, buf, version, flex)?;
389 Self::decode_field_1(&mut out, buf, version, flex)?;
390 Self::decode_field_2(&mut out, buf, version, flex)?;
391 Self::decode_field_3(&mut out, buf, version, flex)?;
392 Self::decode_field_4(&mut out, buf, version, flex)?;
393 Self::decode_field_5(&mut out, buf, version, flex)?;
394 Self::decode_field_6(&mut out, buf, version, flex)?;
395 Self::decode_field_7(&mut out, buf, version, flex)?;
396 Self::decode_tagged_fields(&mut out, buf, version, flex)?;
397 Ok(out)
398 }
399}
400#[cfg(test)]
401impl TxnOffsetCommitRequest<'_> {
402 #[must_use]
403 pub fn populated(version: i16) -> Self {
404 let mut m = Self::default();
405 if version >= 0 {
406 m.transactional_id = "x";
407 }
408 if version >= 0 {
409 m.group_id = "x";
410 }
411 if version >= 0 {
412 m.producer_id = 1i64;
413 }
414 if version >= 0 {
415 m.producer_epoch = 1i16;
416 }
417 if version >= 3 {
418 m.generation_id_or_member_epoch = 1i32;
419 }
420 if version >= 3 {
421 m.member_id = "x";
422 }
423 if version >= 3 {
424 m.group_instance_id = Some("x");
425 }
426 if version >= 0 {
427 m.topics = vec![TxnOffsetCommitRequestTopic::populated(version)];
428 }
429 m
430 }
431}
432#[derive(Debug, Clone, PartialEq, Eq, Default)]
433pub struct TxnOffsetCommitRequestTopic<'a> {
434 pub name: &'a str,
435 pub topic_id: Uuid,
436 pub partitions: Vec<TxnOffsetCommitRequestPartition<'a>>,
437 pub unknown_tagged_fields: UnknownTaggedFields,
438}
439impl TxnOffsetCommitRequestTopic<'_> {
440 #[must_use]
441 pub fn to_owned(&self) -> txn_offset_commit_request::TxnOffsetCommitRequestTopic {
442 txn_offset_commit_request::TxnOffsetCommitRequestTopic {
443 name: (self.name).to_owned(),
444 topic_id: (self.topic_id),
445 partitions: (self.partitions)
446 .iter()
447 .map(TxnOffsetCommitRequestPartition::to_owned)
448 .collect(),
449 unknown_tagged_fields: self.unknown_tagged_fields.clone(),
450 }
451 }
452}
453impl Encode for TxnOffsetCommitRequestTopic<'_> {
454 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
455 let flex = version >= 3;
456 if (0..=5).contains(&version) {
457 if flex {
458 put_compact_string(buf, self.name)?;
459 } else {
460 put_string(buf, self.name)?;
461 }
462 }
463 if version >= 6 {
464 put_uuid(buf, self.topic_id);
465 }
466 if version >= 0 {
467 {
468 put_array_len(buf, (self.partitions).len(), flex)?;
469 for it in &self.partitions {
470 it.encode(buf, version)?;
471 }
472 }
473 }
474 if flex {
475 let tagged = WriteTaggedFields::new();
476 tagged.write(buf, &self.unknown_tagged_fields)?;
477 }
478 Ok(())
479 }
480 fn encoded_len(&self, version: i16) -> usize {
481 let flex = version >= 3;
482 let mut n: usize = 0;
483 if (0..=5).contains(&version) {
484 n += if flex {
485 compact_string_len(self.name)
486 } else {
487 string_len(self.name)
488 };
489 }
490 if version >= 6 {
491 n += 16;
492 }
493 if version >= 0 {
494 n += {
495 let prefix = array_len_prefix_len((self.partitions).len(), flex);
496 let body: usize = (self.partitions)
497 .iter()
498 .map(|it| it.encoded_len(version))
499 .sum();
500 prefix + body
501 };
502 }
503 if flex {
504 let known_pairs: Vec<(u32, usize)> = Vec::new();
505 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
506 }
507 n
508 }
509}
510impl<'de> DecodeBorrow<'de> for TxnOffsetCommitRequestTopic<'de> {
511 fn decode_borrow(buf: &mut &'de [u8], version: i16) -> Result<Self, ProtocolError> {
512 let flex = version >= 3;
513 let mut out = Self::default();
514 if (0..=5).contains(&version) {
515 out.name = if flex {
516 get_compact_string_borrowed(buf)?
517 } else {
518 get_string_borrowed(buf)?
519 };
520 }
521 if version >= 6 {
522 out.topic_id = get_uuid(buf)?;
523 }
524 if version >= 0 {
525 out.partitions = {
526 let n = get_array_len(buf, flex)?;
527 let mut v = Vec::with_capacity(n);
528 for _ in 0..n {
529 v.push(TxnOffsetCommitRequestPartition::decode_borrow(
530 buf, version,
531 )?);
532 }
533 v
534 };
535 }
536 if flex {
537 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
538 }
539 Ok(out)
540 }
541}
542#[cfg(test)]
543impl TxnOffsetCommitRequestTopic<'_> {
544 #[must_use]
545 pub fn populated(version: i16) -> Self {
546 let mut m = Self::default();
547 if (0..=5).contains(&version) {
548 m.name = "x";
549 }
550 if version >= 6 {
551 m.topic_id = Uuid([1u8; 16]);
552 }
553 if version >= 0 {
554 m.partitions = vec![TxnOffsetCommitRequestPartition::populated(version)];
555 }
556 m
557 }
558}
559#[derive(Debug, Clone, PartialEq, Eq)]
560pub struct TxnOffsetCommitRequestPartition<'a> {
561 pub partition_index: i32,
562 pub committed_offset: i64,
563 pub committed_leader_epoch: i32,
564 pub committed_metadata: Option<&'a str>,
565 pub unknown_tagged_fields: UnknownTaggedFields,
566}
567impl Default for TxnOffsetCommitRequestPartition<'_> {
568 fn default() -> Self {
569 Self {
570 partition_index: 0i32,
571 committed_offset: 0i64,
572 committed_leader_epoch: -1i32,
573 committed_metadata: Some(""),
574 unknown_tagged_fields: UnknownTaggedFields::default(),
575 }
576 }
577}
578impl TxnOffsetCommitRequestPartition<'_> {
579 #[must_use]
580 pub fn to_owned(&self) -> txn_offset_commit_request::TxnOffsetCommitRequestPartition {
581 txn_offset_commit_request::TxnOffsetCommitRequestPartition {
582 partition_index: (self.partition_index),
583 committed_offset: (self.committed_offset),
584 committed_leader_epoch: (self.committed_leader_epoch),
585 committed_metadata: (self.committed_metadata).map(str::to_owned),
586 unknown_tagged_fields: self.unknown_tagged_fields.clone(),
587 }
588 }
589}
590impl Encode for TxnOffsetCommitRequestPartition<'_> {
591 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
592 let flex = version >= 3;
593 if version >= 0 {
594 put_i32(buf, self.partition_index);
595 }
596 if version >= 0 {
597 put_i64(buf, self.committed_offset);
598 }
599 if version >= 2 {
600 put_i32(buf, self.committed_leader_epoch);
601 }
602 if version >= 0 {
603 if flex {
604 put_compact_nullable_string(buf, self.committed_metadata)?;
605 } else {
606 put_nullable_string(buf, self.committed_metadata)?;
607 }
608 }
609 if flex {
610 let tagged = WriteTaggedFields::new();
611 tagged.write(buf, &self.unknown_tagged_fields)?;
612 }
613 Ok(())
614 }
615 fn encoded_len(&self, version: i16) -> usize {
616 let flex = version >= 3;
617 let mut n: usize = 0;
618 if version >= 0 {
619 n += 4;
620 }
621 if version >= 0 {
622 n += 8;
623 }
624 if version >= 2 {
625 n += 4;
626 }
627 if version >= 0 {
628 n += if flex {
629 compact_nullable_string_len(self.committed_metadata)
630 } else {
631 nullable_string_len(self.committed_metadata)
632 };
633 }
634 if flex {
635 let known_pairs: Vec<(u32, usize)> = Vec::new();
636 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
637 }
638 n
639 }
640}
641impl<'de> DecodeBorrow<'de> for TxnOffsetCommitRequestPartition<'de> {
642 fn decode_borrow(buf: &mut &'de [u8], version: i16) -> Result<Self, ProtocolError> {
643 let flex = version >= 3;
644 let mut out = Self::default();
645 if version >= 0 {
646 out.partition_index = get_i32(buf)?;
647 }
648 if version >= 0 {
649 out.committed_offset = get_i64(buf)?;
650 }
651 if version >= 2 {
652 out.committed_leader_epoch = get_i32(buf)?;
653 }
654 if version >= 0 {
655 out.committed_metadata = if flex {
656 get_compact_nullable_string_borrowed(buf)?
657 } else {
658 get_nullable_string_borrowed(buf)?
659 };
660 }
661 if flex {
662 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
663 }
664 Ok(out)
665 }
666}
667#[cfg(test)]
668impl TxnOffsetCommitRequestPartition<'_> {
669 #[must_use]
670 pub fn populated(version: i16) -> Self {
671 let mut m = Self::default();
672 if version >= 0 {
673 m.partition_index = 1i32;
674 }
675 if version >= 0 {
676 m.committed_offset = 1i64;
677 }
678 if version >= 2 {
679 m.committed_leader_epoch = 1i32;
680 }
681 if version >= 0 {
682 m.committed_metadata = Some("x");
683 }
684 m
685 }
686}