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