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