1use bytes::{Buf, BufMut};
4
5use crate::{
6 Decode, Encode, ProtocolError, UnknownTaggedFields,
7 codegen_helpers::is_default,
8 primitives::{
9 array::{array_len_prefix_len, get_array_len, put_array_len},
10 fixed::{get_i16, get_i32, get_i64, get_u16, put_i16, put_i32, put_i64, put_u16},
11 string_bytes::{
12 compact_bytes_len_from_size, compact_string_len, get_bytes_owned,
13 get_compact_bytes_owned, get_compact_string_owned, get_string_owned,
14 put_compact_string, put_string, string_len,
15 },
16 },
17 records::RecordsPayload,
18 tagged_fields::{WriteTaggedFields, encode_to_bytes, read_tagged_fields, tagged_fields_len},
19};
20pub const API_KEY: i16 = 59;
21pub const MIN_VERSION: i16 = 0;
22pub const MAX_VERSION: i16 = 1;
23pub const FLEXIBLE_MIN: i16 = 0;
24#[inline]
25#[must_use]
26pub fn is_flexible(version: i16) -> bool {
27 version >= FLEXIBLE_MIN
28}
29#[derive(Debug, Clone, PartialEq, Eq, Default)]
30pub struct FetchSnapshotResponse {
31 pub throttle_time_ms: i32,
32 pub error_code: i16,
33 pub topics: Vec<TopicSnapshot>,
34 pub node_endpoints: Vec<NodeEndpoint>,
35 pub unknown_tagged_fields: UnknownTaggedFields,
36}
37impl Encode for FetchSnapshotResponse {
38 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
39 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
40 return Err(ProtocolError::UnsupportedVersion {
41 api_key: API_KEY,
42 version,
43 });
44 }
45 let flex = is_flexible(version);
46 if version >= 0 {
47 put_i32(buf, self.throttle_time_ms);
48 }
49 if version >= 0 {
50 put_i16(buf, self.error_code);
51 }
52 if version >= 0 {
53 {
54 put_array_len(buf, (self.topics).len(), flex)?;
55 for it in &self.topics {
56 it.encode(buf, version)?;
57 }
58 }
59 }
60 if flex {
61 let mut tagged = WriteTaggedFields::new();
62 if version >= 1 && !(is_default(&self.node_endpoints)) {
63 let payload = encode_to_bytes(
64 {
65 let prefix = array_len_prefix_len((self.node_endpoints).len(), flex);
66 let body: usize = (self.node_endpoints)
67 .iter()
68 .map(|it| it.encoded_len(version))
69 .sum();
70 prefix + body
71 },
72 |b| {
73 {
74 put_array_len(b, (self.node_endpoints).len(), flex)?;
75 for it in &self.node_endpoints {
76 it.encode(b, version)?;
77 }
78 }
79 Ok(())
80 },
81 )?;
82 tagged.add(0, payload);
83 }
84 tagged.write(buf, &self.unknown_tagged_fields)?;
85 }
86 Ok(())
87 }
88 fn encoded_len(&self, version: i16) -> usize {
89 let flex = is_flexible(version);
90 let mut n: usize = 0;
91 if version >= 0 {
92 n += 4;
93 }
94 if version >= 0 {
95 n += 2;
96 }
97 if version >= 0 {
98 n += {
99 let prefix = array_len_prefix_len((self.topics).len(), flex);
100 let body: usize = (self.topics).iter().map(|it| it.encoded_len(version)).sum();
101 prefix + body
102 };
103 }
104 if flex {
105 let mut known_pairs: Vec<(u32, usize)> = Vec::new();
106 if version >= 1 && !(is_default(&self.node_endpoints)) {
107 known_pairs.push((0, {
108 let prefix = array_len_prefix_len((self.node_endpoints).len(), flex);
109 let body: usize = (self.node_endpoints)
110 .iter()
111 .map(|it| it.encoded_len(version))
112 .sum();
113 prefix + body
114 }));
115 }
116 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
117 }
118 n
119 }
120}
121impl Decode<'_> for FetchSnapshotResponse {
122 fn decode<B: Buf>(buf: &mut B, version: i16) -> Result<Self, ProtocolError> {
123 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
124 return Err(ProtocolError::UnsupportedVersion {
125 api_key: API_KEY,
126 version,
127 });
128 }
129 let flex = is_flexible(version);
130 let mut out = Self::default();
131 if version >= 0 {
132 out.throttle_time_ms = get_i32(buf)?;
133 }
134 if version >= 0 {
135 out.error_code = get_i16(buf)?;
136 }
137 if version >= 0 {
138 out.topics = {
139 let n = get_array_len(buf, flex)?;
140 let mut v = Vec::with_capacity(n);
141 for _ in 0..n {
142 v.push(TopicSnapshot::decode(buf, version)?);
143 }
144 v
145 };
146 }
147 if flex {
148 let mut tag_node_endpoints = None;
149 out.unknown_tagged_fields = read_tagged_fields(buf, |tag, payload| match tag {
150 0 if version >= 1 => {
151 tag_node_endpoints = Some({
152 let b: &mut &[u8] = payload;
153 {
154 let n = get_array_len(b, flex)?;
155 let mut v = Vec::with_capacity(n);
156 for _ in 0..n {
157 v.push(NodeEndpoint::decode(b, version)?);
158 }
159 v
160 }
161 });
162 Ok(true)
163 }
164 0 => Err(ProtocolError::TagNotValidForVersion { tag: 0, version }),
165 _ => Ok(false),
166 })?;
167 if let Some(v) = tag_node_endpoints {
168 out.node_endpoints = v;
169 }
170 }
171 Ok(out)
172 }
173}
174#[cfg(test)]
175impl FetchSnapshotResponse {
176 #[must_use]
177 pub fn populated(version: i16) -> Self {
178 let mut m = Self::default();
179 if version >= 0 {
180 m.throttle_time_ms = 1i32;
181 }
182 if version >= 0 {
183 m.error_code = 1i16;
184 }
185 if version >= 0 {
186 m.topics = vec![TopicSnapshot::populated(version)];
187 }
188 if version >= 1 {
189 m.node_endpoints = vec![NodeEndpoint::populated(version)];
190 }
191 m
192 }
193}
194#[derive(Debug, Clone, PartialEq, Eq, Default)]
195pub struct TopicSnapshot {
196 pub name: String,
197 pub partitions: Vec<PartitionSnapshot>,
198 pub unknown_tagged_fields: UnknownTaggedFields,
199}
200impl Encode for TopicSnapshot {
201 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
202 let flex = version >= 0;
203 if version >= 0 {
204 if flex {
205 put_compact_string(buf, &self.name)?;
206 } else {
207 put_string(buf, &self.name)?;
208 }
209 }
210 if version >= 0 {
211 {
212 put_array_len(buf, (self.partitions).len(), flex)?;
213 for it in &self.partitions {
214 it.encode(buf, version)?;
215 }
216 }
217 }
218 if flex {
219 let tagged = WriteTaggedFields::new();
220 tagged.write(buf, &self.unknown_tagged_fields)?;
221 }
222 Ok(())
223 }
224 fn encoded_len(&self, version: i16) -> usize {
225 let flex = version >= 0;
226 let mut n: usize = 0;
227 if version >= 0 {
228 n += if flex {
229 compact_string_len(&self.name)
230 } else {
231 string_len(&self.name)
232 };
233 }
234 if version >= 0 {
235 n += {
236 let prefix = array_len_prefix_len((self.partitions).len(), flex);
237 let body: usize = (self.partitions)
238 .iter()
239 .map(|it| it.encoded_len(version))
240 .sum();
241 prefix + body
242 };
243 }
244 if flex {
245 let known_pairs: Vec<(u32, usize)> = Vec::new();
246 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
247 }
248 n
249 }
250}
251impl Decode<'_> for TopicSnapshot {
252 fn decode<B: Buf>(buf: &mut B, version: i16) -> Result<Self, ProtocolError> {
253 let flex = version >= 0;
254 let mut out = Self::default();
255 if version >= 0 {
256 out.name = if flex {
257 get_compact_string_owned(buf)?
258 } else {
259 get_string_owned(buf)?
260 };
261 }
262 if version >= 0 {
263 out.partitions = {
264 let n = get_array_len(buf, flex)?;
265 let mut v = Vec::with_capacity(n);
266 for _ in 0..n {
267 v.push(PartitionSnapshot::decode(buf, version)?);
268 }
269 v
270 };
271 }
272 if flex {
273 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
274 }
275 Ok(out)
276 }
277}
278#[cfg(test)]
279impl TopicSnapshot {
280 #[must_use]
281 pub fn populated(version: i16) -> Self {
282 let mut m = Self::default();
283 if version >= 0 {
284 m.name = "x".to_owned();
285 }
286 if version >= 0 {
287 m.partitions = vec![PartitionSnapshot::populated(version)];
288 }
289 m
290 }
291}
292#[derive(Debug, Clone, PartialEq, Eq, Default)]
293pub struct PartitionSnapshot {
294 pub index: i32,
295 pub error_code: i16,
296 pub snapshot_id: SnapshotId,
297 pub size: i64,
298 pub position: i64,
299 pub unaligned_records: RecordsPayload,
300 pub current_leader: LeaderIdAndEpoch,
301 pub unknown_tagged_fields: UnknownTaggedFields,
302}
303impl Encode for PartitionSnapshot {
304 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
305 let flex = version >= 0;
306 if version >= 0 {
307 put_i32(buf, self.index);
308 }
309 if version >= 0 {
310 put_i16(buf, self.error_code);
311 }
312 if version >= 0 {
313 self.snapshot_id.encode(buf, version)?;
314 }
315 if version >= 0 {
316 put_i64(buf, self.size);
317 }
318 if version >= 0 {
319 put_i64(buf, self.position);
320 }
321 if version >= 0 {
322 self.unaligned_records
323 .encode_length_prefixed(buf, version, flex)?;
324 }
325 if flex {
326 let mut tagged = WriteTaggedFields::new();
327 if !(is_default(&self.current_leader)) {
328 let payload = encode_to_bytes(self.current_leader.encoded_len(version), |b| {
329 self.current_leader.encode(b, version)?;
330 Ok(())
331 })?;
332 tagged.add(0, payload);
333 }
334 tagged.write(buf, &self.unknown_tagged_fields)?;
335 }
336 Ok(())
337 }
338 fn encoded_len(&self, version: i16) -> usize {
339 let flex = version >= 0;
340 let mut n: usize = 0;
341 if version >= 0 {
342 n += 4;
343 }
344 if version >= 0 {
345 n += 2;
346 }
347 if version >= 0 {
348 n += self.snapshot_id.encoded_len(version);
349 }
350 if version >= 0 {
351 n += 8;
352 }
353 if version >= 0 {
354 n += 8;
355 }
356 if version >= 0 {
357 n += {
358 let __rb_len = <RecordsPayload as crate::Encode>::encoded_len(
359 &self.unaligned_records,
360 version,
361 );
362 if flex {
363 compact_bytes_len_from_size(__rb_len)
364 } else {
365 4 + __rb_len
366 }
367 };
368 }
369 if flex {
370 let mut known_pairs: Vec<(u32, usize)> = Vec::new();
371 if !(is_default(&self.current_leader)) {
372 known_pairs.push((0, self.current_leader.encoded_len(version)));
373 }
374 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
375 }
376 n
377 }
378}
379impl Decode<'_> for PartitionSnapshot {
380 fn decode<B: Buf>(buf: &mut B, version: i16) -> Result<Self, ProtocolError> {
381 let flex = version >= 0;
382 let mut out = Self::default();
383 if version >= 0 {
384 out.index = get_i32(buf)?;
385 }
386 if version >= 0 {
387 out.error_code = get_i16(buf)?;
388 }
389 if version >= 0 {
390 out.snapshot_id = SnapshotId::decode(buf, version)?;
391 }
392 if version >= 0 {
393 out.size = get_i64(buf)?;
394 }
395 if version >= 0 {
396 out.position = get_i64(buf)?;
397 }
398 if version >= 0 {
399 out.unaligned_records = {
400 let __rb_bytes = if flex {
401 get_compact_bytes_owned(buf)?
402 } else {
403 get_bytes_owned(buf)?
404 };
405 RecordsPayload::from_fetch_bytes(__rb_bytes)?
406 };
407 }
408 if flex {
409 let mut tag_current_leader = None;
410 out.unknown_tagged_fields = read_tagged_fields(buf, |tag, payload| match tag {
411 0 => {
412 tag_current_leader = Some({
413 let b: &mut &[u8] = payload;
414 LeaderIdAndEpoch::decode(b, version)?
415 });
416 Ok(true)
417 }
418 _ => Ok(false),
419 })?;
420 if let Some(v) = tag_current_leader {
421 out.current_leader = v;
422 }
423 }
424 Ok(out)
425 }
426}
427#[cfg(test)]
428impl PartitionSnapshot {
429 #[must_use]
430 pub fn populated(version: i16) -> Self {
431 let mut m = Self::default();
432 if version >= 0 {
433 m.index = 1i32;
434 }
435 if version >= 0 {
436 m.error_code = 1i16;
437 }
438 if version >= 0 {
439 m.snapshot_id = SnapshotId::populated(version);
440 }
441 if version >= 0 {
442 m.size = 1i64;
443 }
444 if version >= 0 {
445 m.position = 1i64;
446 }
447 if version >= 0 {
448 m.current_leader = LeaderIdAndEpoch::populated(version);
449 }
450 m
451 }
452}
453#[derive(Debug, Clone, PartialEq, Eq, Default)]
454pub struct SnapshotId {
455 pub end_offset: i64,
456 pub epoch: i32,
457 pub unknown_tagged_fields: UnknownTaggedFields,
458}
459impl Encode for SnapshotId {
460 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
461 let flex = version >= 0;
462 if version >= 0 {
463 put_i64(buf, self.end_offset);
464 }
465 if version >= 0 {
466 put_i32(buf, self.epoch);
467 }
468 if flex {
469 let tagged = WriteTaggedFields::new();
470 tagged.write(buf, &self.unknown_tagged_fields)?;
471 }
472 Ok(())
473 }
474 fn encoded_len(&self, version: i16) -> usize {
475 let flex = version >= 0;
476 let mut n: usize = 0;
477 if version >= 0 {
478 n += 8;
479 }
480 if version >= 0 {
481 n += 4;
482 }
483 if flex {
484 let known_pairs: Vec<(u32, usize)> = Vec::new();
485 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
486 }
487 n
488 }
489}
490impl Decode<'_> for SnapshotId {
491 fn decode<B: Buf>(buf: &mut B, version: i16) -> Result<Self, ProtocolError> {
492 let flex = version >= 0;
493 let mut out = Self::default();
494 if version >= 0 {
495 out.end_offset = get_i64(buf)?;
496 }
497 if version >= 0 {
498 out.epoch = get_i32(buf)?;
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 SnapshotId {
508 #[must_use]
509 pub fn populated(version: i16) -> Self {
510 let mut m = Self::default();
511 if version >= 0 {
512 m.end_offset = 1i64;
513 }
514 if version >= 0 {
515 m.epoch = 1i32;
516 }
517 m
518 }
519}
520#[derive(Debug, Clone, PartialEq, Eq, Default)]
521pub struct LeaderIdAndEpoch {
522 pub leader_id: i32,
523 pub leader_epoch: i32,
524 pub unknown_tagged_fields: UnknownTaggedFields,
525}
526impl Encode for LeaderIdAndEpoch {
527 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
528 let flex = version >= 0;
529 if version >= 0 {
530 put_i32(buf, self.leader_id);
531 }
532 if version >= 0 {
533 put_i32(buf, self.leader_epoch);
534 }
535 if flex {
536 let tagged = WriteTaggedFields::new();
537 tagged.write(buf, &self.unknown_tagged_fields)?;
538 }
539 Ok(())
540 }
541 fn encoded_len(&self, version: i16) -> usize {
542 let flex = version >= 0;
543 let mut n: usize = 0;
544 if version >= 0 {
545 n += 4;
546 }
547 if version >= 0 {
548 n += 4;
549 }
550 if flex {
551 let known_pairs: Vec<(u32, usize)> = Vec::new();
552 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
553 }
554 n
555 }
556}
557impl Decode<'_> for LeaderIdAndEpoch {
558 fn decode<B: Buf>(buf: &mut B, version: i16) -> Result<Self, ProtocolError> {
559 let flex = version >= 0;
560 let mut out = Self::default();
561 if version >= 0 {
562 out.leader_id = get_i32(buf)?;
563 }
564 if version >= 0 {
565 out.leader_epoch = get_i32(buf)?;
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 LeaderIdAndEpoch {
575 #[must_use]
576 pub fn populated(version: i16) -> Self {
577 let mut m = Self::default();
578 if version >= 0 {
579 m.leader_id = 1i32;
580 }
581 if version >= 0 {
582 m.leader_epoch = 1i32;
583 }
584 m
585 }
586}
587#[derive(Debug, Clone, PartialEq, Eq, Default)]
588pub struct NodeEndpoint {
589 pub node_id: i32,
590 pub host: String,
591 pub port: u16,
592 pub unknown_tagged_fields: UnknownTaggedFields,
593}
594impl Encode for NodeEndpoint {
595 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
596 let flex = version >= 0;
597 if version >= 1 {
598 put_i32(buf, self.node_id);
599 }
600 if version >= 1 {
601 if flex {
602 put_compact_string(buf, &self.host)?;
603 } else {
604 put_string(buf, &self.host)?;
605 }
606 }
607 if version >= 1 {
608 put_u16(buf, self.port);
609 }
610 if flex {
611 let tagged = WriteTaggedFields::new();
612 tagged.write(buf, &self.unknown_tagged_fields)?;
613 }
614 Ok(())
615 }
616 fn encoded_len(&self, version: i16) -> usize {
617 let flex = version >= 0;
618 let mut n: usize = 0;
619 if version >= 1 {
620 n += 4;
621 }
622 if version >= 1 {
623 n += if flex {
624 compact_string_len(&self.host)
625 } else {
626 string_len(&self.host)
627 };
628 }
629 if version >= 1 {
630 n += 2;
631 }
632 if flex {
633 let known_pairs: Vec<(u32, usize)> = Vec::new();
634 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
635 }
636 n
637 }
638}
639impl Decode<'_> for NodeEndpoint {
640 fn decode<B: Buf>(buf: &mut B, version: i16) -> Result<Self, ProtocolError> {
641 let flex = version >= 0;
642 let mut out = Self::default();
643 if version >= 1 {
644 out.node_id = get_i32(buf)?;
645 }
646 if version >= 1 {
647 out.host = if flex {
648 get_compact_string_owned(buf)?
649 } else {
650 get_string_owned(buf)?
651 };
652 }
653 if version >= 1 {
654 out.port = get_u16(buf)?;
655 }
656 if flex {
657 out.unknown_tagged_fields = read_tagged_fields(buf, |_tag, _payload| Ok(false))?;
658 }
659 Ok(out)
660 }
661}
662#[cfg(test)]
663impl NodeEndpoint {
664 #[must_use]
665 pub fn populated(version: i16) -> Self {
666 let mut m = Self::default();
667 if version >= 1 {
668 m.node_id = 1i32;
669 }
670 if version >= 1 {
671 m.host = "x".to_owned();
672 }
673 if version >= 1 {
674 m.port = 1u16;
675 }
676 m
677 }
678}
679#[must_use]
682#[allow(unused_comparisons)]
683pub fn default_json(version: i16) -> ::serde_json::Value {
684 let mut obj = ::serde_json::Map::new();
685 obj.insert("throttleTimeMs".to_owned(), ::serde_json::json!(0));
686 obj.insert("errorCode".to_owned(), ::serde_json::json!(0));
687 obj.insert("topics".to_owned(), ::serde_json::Value::Array(vec![]));
688 if version >= 1 {
689 obj.insert(
690 "nodeEndpoints".to_owned(),
691 ::serde_json::Value::Array(vec![]),
692 );
693 }
694 ::serde_json::Value::Object(obj)
695}
696#[must_use]
699pub fn tagged_fixture() -> FetchSnapshotResponse {
700 FetchSnapshotResponse {
701 topics: vec![TopicSnapshot {
702 partitions: vec![PartitionSnapshot {
703 current_leader: LeaderIdAndEpoch {
704 leader_id: 1i32,
705 leader_epoch: 1i32,
706 ..LeaderIdAndEpoch::default()
707 },
708 ..PartitionSnapshot::default()
709 }],
710 ..TopicSnapshot::default()
711 }],
712 node_endpoints: vec![NodeEndpoint {
713 node_id: 1i32,
714 host: "x".to_owned(),
715 port: 1u16,
716 ..NodeEndpoint::default()
717 }],
718 ..FetchSnapshotResponse::default()
719 }
720}
721#[must_use]
724pub fn tagged_fixture_json(version: i16) -> ::serde_json::Value {
725 let mut m = ::serde_json::Map::new();
726 m.insert("throttleTimeMs".to_owned(), ::serde_json::json!(0));
727 m.insert("errorCode".to_owned(), ::serde_json::json!(0));
728 m.insert(
729 "topics".to_owned(),
730 ::serde_json::Value::Array(vec![{
731 let mut m = ::serde_json::Map::new();
732 m.insert(
733 "name".to_owned(),
734 ::serde_json::Value::String(String::new()),
735 );
736 m.insert(
737 "partitions".to_owned(),
738 ::serde_json::Value::Array(vec![{
739 let mut m = ::serde_json::Map::new();
740 m.insert("index".to_owned(), ::serde_json::json!(0));
741 m.insert("errorCode".to_owned(), ::serde_json::json!(0));
742 m.insert("snapshotId".to_owned(), {
743 let mut m = ::serde_json::Map::new();
744 m.insert("endOffset".to_owned(), ::serde_json::json!(0));
745 m.insert("epoch".to_owned(), ::serde_json::json!(0));
746 ::serde_json::Value::Object(m)
747 });
748 m.insert("currentLeader".to_owned(), {
749 let mut m = ::serde_json::Map::new();
750 m.insert("leaderId".to_owned(), ::serde_json::json!(1));
751 m.insert("leaderEpoch".to_owned(), ::serde_json::json!(1));
752 ::serde_json::Value::Object(m)
753 });
754 m.insert("size".to_owned(), ::serde_json::json!(0));
755 m.insert("position".to_owned(), ::serde_json::json!(0));
756 m.insert(
757 "unalignedRecords".to_owned(),
758 ::serde_json::Value::String(String::new()),
759 );
760 ::serde_json::Value::Object(m)
761 }]),
762 );
763 ::serde_json::Value::Object(m)
764 }]),
765 );
766 if version == 1 {
767 m.insert(
768 "nodeEndpoints".to_owned(),
769 ::serde_json::Value::Array(vec![{
770 let mut m = ::serde_json::Map::new();
771 m.insert("nodeId".to_owned(), ::serde_json::json!(1));
772 m.insert(
773 "host".to_owned(),
774 ::serde_json::Value::String("x".to_owned()),
775 );
776 m.insert("port".to_owned(), ::serde_json::json!(1));
777 ::serde_json::Value::Object(m)
778 }]),
779 );
780 }
781 ::serde_json::Value::Object(m)
782}