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