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