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