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_i8, get_i32, put_i8, put_i32},
13 uuid::{Uuid, get_uuid, put_uuid},
14 },
15 tagged_fields::{WriteTaggedFields, encode_to_bytes, read_tagged_fields, tagged_fields_len},
16};
17pub const MIN_VERSION: i16 = 0;
18pub const MAX_VERSION: i16 = 2;
19pub const FLEXIBLE_MIN: i16 = 0;
20#[inline]
21#[must_use]
22pub fn is_flexible(version: i16) -> bool {
23 version >= FLEXIBLE_MIN
24}
25#[derive(Debug, Clone, PartialEq, Eq)]
26pub struct PartitionRecord {
27 pub partition_id: i32,
28 pub topic_id: Uuid,
29 pub replicas: Vec<i32>,
30 pub isr: Vec<i32>,
31 pub removing_replicas: Vec<i32>,
32 pub adding_replicas: Vec<i32>,
33 pub leader: i32,
34 pub leader_epoch: i32,
35 pub partition_epoch: i32,
36 pub directories: Vec<Uuid>,
37 pub leader_recovery_state: i8,
38 pub eligible_leader_replicas: Option<Vec<i32>>,
39 pub last_known_elr: Option<Vec<i32>>,
40 pub unknown_tagged_fields: UnknownTaggedFields,
41}
42impl Default for PartitionRecord {
43 fn default() -> Self {
44 Self {
45 partition_id: -1i32,
46 topic_id: Uuid::default(),
47 replicas: Vec::new(),
48 isr: Vec::new(),
49 removing_replicas: Vec::new(),
50 adding_replicas: Vec::new(),
51 leader: -1i32,
52 leader_epoch: -1i32,
53 partition_epoch: -1i32,
54 directories: Vec::new(),
55 leader_recovery_state: 0i8,
56 eligible_leader_replicas: None,
57 last_known_elr: None,
58 unknown_tagged_fields: UnknownTaggedFields::default(),
59 }
60 }
61}
62impl PartitionRecord {
63 fn encode_field_0<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
64 if version >= 0 {
65 put_i32(buf, self.partition_id);
66 }
67 }
68 fn encode_field_1<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
69 if version >= 0 {
70 put_uuid(buf, self.topic_id);
71 }
72 }
73 fn encode_field_2<B: BufMut>(
74 &self,
75 buf: &mut B,
76 version: i16,
77 flex: bool,
78 ) -> Result<(), ProtocolError> {
79 if version >= 0 {
80 {
81 put_array_len(buf, (self.replicas).len(), flex)?;
82 for it in &self.replicas {
83 put_i32(buf, *it);
84 }
85 }
86 }
87 Ok(())
88 }
89 fn encode_field_3<B: BufMut>(
90 &self,
91 buf: &mut B,
92 version: i16,
93 flex: bool,
94 ) -> Result<(), ProtocolError> {
95 if version >= 0 {
96 {
97 put_array_len(buf, (self.isr).len(), flex)?;
98 for it in &self.isr {
99 put_i32(buf, *it);
100 }
101 }
102 }
103 Ok(())
104 }
105 fn encode_field_4<B: BufMut>(
106 &self,
107 buf: &mut B,
108 version: i16,
109 flex: bool,
110 ) -> Result<(), ProtocolError> {
111 if version >= 0 {
112 {
113 put_array_len(buf, (self.removing_replicas).len(), flex)?;
114 for it in &self.removing_replicas {
115 put_i32(buf, *it);
116 }
117 }
118 }
119 Ok(())
120 }
121 fn encode_field_5<B: BufMut>(
122 &self,
123 buf: &mut B,
124 version: i16,
125 flex: bool,
126 ) -> Result<(), ProtocolError> {
127 if version >= 0 {
128 {
129 put_array_len(buf, (self.adding_replicas).len(), flex)?;
130 for it in &self.adding_replicas {
131 put_i32(buf, *it);
132 }
133 }
134 }
135 Ok(())
136 }
137 fn encode_field_6<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
138 if version >= 0 {
139 put_i32(buf, self.leader);
140 }
141 }
142 fn encode_field_7<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
143 if version >= 0 {
144 put_i32(buf, self.leader_epoch);
145 }
146 }
147 fn encode_field_8<B: BufMut>(&self, buf: &mut B, version: i16, _flex: bool) {
148 if version >= 0 {
149 put_i32(buf, self.partition_epoch);
150 }
151 }
152 fn encode_field_9<B: BufMut>(
153 &self,
154 buf: &mut B,
155 version: i16,
156 flex: bool,
157 ) -> Result<(), ProtocolError> {
158 if version >= 1 {
159 {
160 put_array_len(buf, (self.directories).len(), flex)?;
161 for it in &self.directories {
162 put_uuid(buf, *it);
163 }
164 }
165 }
166 Ok(())
167 }
168 fn encode_tagged_fields<B: BufMut>(
169 &self,
170 buf: &mut B,
171 version: i16,
172 flex: bool,
173 ) -> Result<(), ProtocolError> {
174 if flex {
175 let mut tagged = WriteTaggedFields::new();
176 if self.leader_recovery_state != 0i8 {
177 let payload = encode_to_bytes(1, |b| {
178 put_i8(b, self.leader_recovery_state);
179 Ok(())
180 })?;
181 tagged.add(0, payload);
182 }
183 if version >= 2 && self.eligible_leader_replicas.is_some() {
184 let payload = encode_to_bytes(
185 {
186 let opt: Option<&Vec<_>> = (self.eligible_leader_replicas).as_ref();
187 let prefix = nullable_array_len_prefix_len(opt.map(Vec::len), flex);
188 let body: usize = opt.map_or(0, |v| v.iter().map(|_| 4).sum());
189 prefix + body
190 },
191 |b| {
192 {
193 let len = (self.eligible_leader_replicas).as_ref().map(Vec::len);
194 put_nullable_array_len(b, len, flex)?;
195 if let Some(v) = &self.eligible_leader_replicas {
196 for it in v {
197 put_i32(b, *it);
198 }
199 }
200 }
201 Ok(())
202 },
203 )?;
204 tagged.add(1, payload);
205 }
206 if version >= 2 && self.last_known_elr.is_some() {
207 let payload = encode_to_bytes(
208 {
209 let opt: Option<&Vec<_>> = (self.last_known_elr).as_ref();
210 let prefix = nullable_array_len_prefix_len(opt.map(Vec::len), flex);
211 let body: usize = opt.map_or(0, |v| v.iter().map(|_| 4).sum());
212 prefix + body
213 },
214 |b| {
215 {
216 let len = (self.last_known_elr).as_ref().map(Vec::len);
217 put_nullable_array_len(b, len, flex)?;
218 if let Some(v) = &self.last_known_elr {
219 for it in v {
220 put_i32(b, *it);
221 }
222 }
223 }
224 Ok(())
225 },
226 )?;
227 tagged.add(2, payload);
228 }
229 tagged.write(buf, &self.unknown_tagged_fields)?;
230 }
231 Ok(())
232 }
233 fn decode_field_0<B: Buf>(
234 out: &mut Self,
235 buf: &mut B,
236 version: i16,
237 _flex: bool,
238 ) -> Result<(), ProtocolError> {
239 if version >= 0 {
240 out.partition_id = get_i32(buf)?;
241 }
242 Ok(())
243 }
244 fn decode_field_1<B: Buf>(
245 out: &mut Self,
246 buf: &mut B,
247 version: i16,
248 _flex: bool,
249 ) -> Result<(), ProtocolError> {
250 if version >= 0 {
251 out.topic_id = get_uuid(buf)?;
252 }
253 Ok(())
254 }
255 fn decode_field_2<B: Buf>(
256 out: &mut Self,
257 buf: &mut B,
258 version: i16,
259 flex: bool,
260 ) -> Result<(), ProtocolError> {
261 if version >= 0 {
262 out.replicas = {
263 let n = get_array_len(buf, flex)?;
264 let mut v = Vec::with_capacity(n);
265 for _ in 0..n {
266 v.push(get_i32(buf)?);
267 }
268 v
269 };
270 }
271 Ok(())
272 }
273 fn decode_field_3<B: Buf>(
274 out: &mut Self,
275 buf: &mut B,
276 version: i16,
277 flex: bool,
278 ) -> Result<(), ProtocolError> {
279 if version >= 0 {
280 out.isr = {
281 let n = get_array_len(buf, flex)?;
282 let mut v = Vec::with_capacity(n);
283 for _ in 0..n {
284 v.push(get_i32(buf)?);
285 }
286 v
287 };
288 }
289 Ok(())
290 }
291 fn decode_field_4<B: Buf>(
292 out: &mut Self,
293 buf: &mut B,
294 version: i16,
295 flex: bool,
296 ) -> Result<(), ProtocolError> {
297 if version >= 0 {
298 out.removing_replicas = {
299 let n = get_array_len(buf, flex)?;
300 let mut v = Vec::with_capacity(n);
301 for _ in 0..n {
302 v.push(get_i32(buf)?);
303 }
304 v
305 };
306 }
307 Ok(())
308 }
309 fn decode_field_5<B: Buf>(
310 out: &mut Self,
311 buf: &mut B,
312 version: i16,
313 flex: bool,
314 ) -> Result<(), ProtocolError> {
315 if version >= 0 {
316 out.adding_replicas = {
317 let n = get_array_len(buf, flex)?;
318 let mut v = Vec::with_capacity(n);
319 for _ in 0..n {
320 v.push(get_i32(buf)?);
321 }
322 v
323 };
324 }
325 Ok(())
326 }
327 fn decode_field_6<B: Buf>(
328 out: &mut Self,
329 buf: &mut B,
330 version: i16,
331 _flex: bool,
332 ) -> Result<(), ProtocolError> {
333 if version >= 0 {
334 out.leader = get_i32(buf)?;
335 }
336 Ok(())
337 }
338 fn decode_field_7<B: Buf>(
339 out: &mut Self,
340 buf: &mut B,
341 version: i16,
342 _flex: bool,
343 ) -> Result<(), ProtocolError> {
344 if version >= 0 {
345 out.leader_epoch = get_i32(buf)?;
346 }
347 Ok(())
348 }
349 fn decode_field_8<B: Buf>(
350 out: &mut Self,
351 buf: &mut B,
352 version: i16,
353 _flex: bool,
354 ) -> Result<(), ProtocolError> {
355 if version >= 0 {
356 out.partition_epoch = get_i32(buf)?;
357 }
358 Ok(())
359 }
360 fn decode_field_9<B: Buf>(
361 out: &mut Self,
362 buf: &mut B,
363 version: i16,
364 flex: bool,
365 ) -> Result<(), ProtocolError> {
366 if version >= 1 {
367 out.directories = {
368 let n = get_array_len(buf, flex)?;
369 let mut v = Vec::with_capacity(n);
370 for _ in 0..n {
371 v.push(get_uuid(buf)?);
372 }
373 v
374 };
375 }
376 Ok(())
377 }
378 fn decode_tagged_fields<B: Buf>(
379 out: &mut Self,
380 buf: &mut B,
381 version: i16,
382 flex: bool,
383 ) -> Result<(), ProtocolError> {
384 if flex {
385 let mut tag_leader_recovery_state = None;
386 let mut tag_eligible_leader_replicas = None;
387 let mut tag_last_known_elr = None;
388 out.unknown_tagged_fields = read_tagged_fields(buf, |tag, payload| match tag {
389 0 => {
390 tag_leader_recovery_state = Some({
391 let b: &mut &[u8] = payload;
392 get_i8(b)?
393 });
394 Ok(true)
395 }
396 1 if version >= 2 => {
397 tag_eligible_leader_replicas = Some({
398 let b: &mut &[u8] = payload;
399 {
400 let opt = get_nullable_array_len(b, flex)?;
401 match opt {
402 None => None,
403 Some(n) => {
404 let mut v = Vec::with_capacity(n);
405 for _ in 0..n {
406 v.push(get_i32(b)?);
407 }
408 Some(v)
409 }
410 }
411 }
412 });
413 Ok(true)
414 }
415 1 => Err(ProtocolError::TagNotValidForVersion { tag: 1, version }),
416 2 if version >= 2 => {
417 tag_last_known_elr = Some({
418 let b: &mut &[u8] = payload;
419 {
420 let opt = get_nullable_array_len(b, flex)?;
421 match opt {
422 None => None,
423 Some(n) => {
424 let mut v = Vec::with_capacity(n);
425 for _ in 0..n {
426 v.push(get_i32(b)?);
427 }
428 Some(v)
429 }
430 }
431 }
432 });
433 Ok(true)
434 }
435 2 => Err(ProtocolError::TagNotValidForVersion { tag: 2, version }),
436 _ => Ok(false),
437 })?;
438 if let Some(v) = tag_leader_recovery_state {
439 out.leader_recovery_state = v;
440 }
441 if let Some(v) = tag_eligible_leader_replicas {
442 out.eligible_leader_replicas = v;
443 }
444 if let Some(v) = tag_last_known_elr {
445 out.last_known_elr = v;
446 }
447 }
448 Ok(())
449 }
450}
451impl Encode for PartitionRecord {
452 fn encode<B: BufMut>(&self, buf: &mut B, version: i16) -> Result<(), ProtocolError> {
453 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
454 return Err(ProtocolError::SchemaMismatch(
455 "PartitionRecord version out of range",
456 ));
457 }
458 let flex = is_flexible(version);
459 self.encode_field_0(buf, version, flex);
460 self.encode_field_1(buf, version, flex);
461 self.encode_field_2(buf, version, flex)?;
462 self.encode_field_3(buf, version, flex)?;
463 self.encode_field_4(buf, version, flex)?;
464 self.encode_field_5(buf, version, flex)?;
465 self.encode_field_6(buf, version, flex);
466 self.encode_field_7(buf, version, flex);
467 self.encode_field_8(buf, version, flex);
468 self.encode_field_9(buf, version, flex)?;
469 self.encode_tagged_fields(buf, version, flex)?;
470 Ok(())
471 }
472 fn encoded_len(&self, version: i16) -> usize {
473 let flex = is_flexible(version);
474 let mut n: usize = 0;
475 if version >= 0 {
476 n += 4;
477 }
478 if version >= 0 {
479 n += 16;
480 }
481 if version >= 0 {
482 n += {
483 let prefix = array_len_prefix_len((self.replicas).len(), flex);
484 let body: usize = (self.replicas).iter().map(|_| 4).sum();
485 prefix + body
486 };
487 }
488 if version >= 0 {
489 n += {
490 let prefix = array_len_prefix_len((self.isr).len(), flex);
491 let body: usize = (self.isr).iter().map(|_| 4).sum();
492 prefix + body
493 };
494 }
495 if version >= 0 {
496 n += {
497 let prefix = array_len_prefix_len((self.removing_replicas).len(), flex);
498 let body: usize = (self.removing_replicas).iter().map(|_| 4).sum();
499 prefix + body
500 };
501 }
502 if version >= 0 {
503 n += {
504 let prefix = array_len_prefix_len((self.adding_replicas).len(), flex);
505 let body: usize = (self.adding_replicas).iter().map(|_| 4).sum();
506 prefix + body
507 };
508 }
509 if version >= 0 {
510 n += 4;
511 }
512 if version >= 0 {
513 n += 4;
514 }
515 if version >= 0 {
516 n += 4;
517 }
518 if version >= 1 {
519 n += {
520 let prefix = array_len_prefix_len((self.directories).len(), flex);
521 let body: usize = (self.directories).iter().map(|_| 16).sum();
522 prefix + body
523 };
524 }
525 if flex {
526 let mut known_pairs: Vec<(u32, usize)> = Vec::new();
527 if self.leader_recovery_state != 0i8 {
528 known_pairs.push((0, 1));
529 }
530 if version >= 2 && self.eligible_leader_replicas.is_some() {
531 known_pairs.push((1, {
532 let opt: Option<&Vec<_>> = (self.eligible_leader_replicas).as_ref();
533 let prefix = nullable_array_len_prefix_len(opt.map(Vec::len), flex);
534 let body: usize = opt.map_or(0, |v| v.iter().map(|_| 4).sum());
535 prefix + body
536 }));
537 }
538 if version >= 2 && self.last_known_elr.is_some() {
539 known_pairs.push((2, {
540 let opt: Option<&Vec<_>> = (self.last_known_elr).as_ref();
541 let prefix = nullable_array_len_prefix_len(opt.map(Vec::len), flex);
542 let body: usize = opt.map_or(0, |v| v.iter().map(|_| 4).sum());
543 prefix + body
544 }));
545 }
546 n += tagged_fields_len(&known_pairs, &self.unknown_tagged_fields);
547 }
548 n
549 }
550}
551impl Decode<'_> for PartitionRecord {
552 fn decode<B: Buf>(buf: &mut B, version: i16) -> Result<Self, ProtocolError> {
553 if !(MIN_VERSION..=MAX_VERSION).contains(&version) {
554 return Err(ProtocolError::SchemaMismatch(
555 "PartitionRecord version out of range",
556 ));
557 }
558 let flex = is_flexible(version);
559 let mut out = Self::default();
560 Self::decode_field_0(&mut out, buf, version, flex)?;
561 Self::decode_field_1(&mut out, buf, version, flex)?;
562 Self::decode_field_2(&mut out, buf, version, flex)?;
563 Self::decode_field_3(&mut out, buf, version, flex)?;
564 Self::decode_field_4(&mut out, buf, version, flex)?;
565 Self::decode_field_5(&mut out, buf, version, flex)?;
566 Self::decode_field_6(&mut out, buf, version, flex)?;
567 Self::decode_field_7(&mut out, buf, version, flex)?;
568 Self::decode_field_8(&mut out, buf, version, flex)?;
569 Self::decode_field_9(&mut out, buf, version, flex)?;
570 Self::decode_tagged_fields(&mut out, buf, version, flex)?;
571 Ok(out)
572 }
573}
574#[cfg(test)]
575impl PartitionRecord {
576 #[must_use]
577 pub fn populated(version: i16) -> Self {
578 let mut m = Self::default();
579 if version >= 0 {
580 m.partition_id = 1i32;
581 }
582 if version >= 0 {
583 m.topic_id = Uuid([1u8; 16]);
584 }
585 if version >= 0 {
586 m.replicas = vec![1i32];
587 }
588 if version >= 0 {
589 m.isr = vec![1i32];
590 }
591 if version >= 0 {
592 m.removing_replicas = vec![1i32];
593 }
594 if version >= 0 {
595 m.adding_replicas = vec![1i32];
596 }
597 if version >= 0 {
598 m.leader = 1i32;
599 }
600 if version >= 0 {
601 m.leader_epoch = 1i32;
602 }
603 if version >= 0 {
604 m.partition_epoch = 1i32;
605 }
606 if version >= 1 {
607 m.directories = vec![Uuid([1u8; 16])];
608 }
609 if version >= 0 {
610 m.leader_recovery_state = 1i8;
611 }
612 if version >= 2 {
613 m.eligible_leader_replicas = Some(vec![1i32]);
614 }
615 if version >= 2 {
616 m.last_known_elr = Some(vec![1i32]);
617 }
618 m
619 }
620}
621#[must_use]
624#[allow(unused_comparisons)]
625pub fn default_json(version: i16) -> ::serde_json::Value {
626 let mut obj = ::serde_json::Map::new();
627 obj.insert("partitionId".to_owned(), ::serde_json::json!(-1));
628 obj.insert(
629 "topicId".to_owned(),
630 ::serde_json::Value::String("AAAAAAAAAAAAAAAAAAAAAA".to_owned()),
631 );
632 obj.insert("replicas".to_owned(), ::serde_json::Value::Array(vec![]));
633 obj.insert("isr".to_owned(), ::serde_json::Value::Array(vec![]));
634 obj.insert(
635 "removingReplicas".to_owned(),
636 ::serde_json::Value::Array(vec![]),
637 );
638 obj.insert(
639 "addingReplicas".to_owned(),
640 ::serde_json::Value::Array(vec![]),
641 );
642 obj.insert("leader".to_owned(), ::serde_json::json!(-1));
643 obj.insert("leaderRecoveryState".to_owned(), ::serde_json::json!(0));
644 obj.insert("leaderEpoch".to_owned(), ::serde_json::json!(-1));
645 obj.insert("partitionEpoch".to_owned(), ::serde_json::json!(-1));
646 if version >= 1 {
647 obj.insert("directories".to_owned(), ::serde_json::Value::Array(vec![]));
648 }
649 if version >= 2 {
650 obj.insert(
651 "eligibleLeaderReplicas".to_owned(),
652 ::serde_json::Value::Null,
653 );
654 }
655 if version >= 2 {
656 obj.insert("lastKnownElr".to_owned(), ::serde_json::Value::Null);
657 }
658 ::serde_json::Value::Object(obj)
659}
660#[must_use]
663pub fn tagged_fixture() -> PartitionRecord {
664 PartitionRecord {
665 leader_recovery_state: 1i8,
666 eligible_leader_replicas: Some(vec![1i32]),
667 last_known_elr: Some(vec![1i32]),
668 ..PartitionRecord::default()
669 }
670}
671#[must_use]
674pub fn tagged_fixture_json(version: i16) -> ::serde_json::Value {
675 let mut m = ::serde_json::Map::new();
676 m.insert("partitionId".to_owned(), ::serde_json::json!(-1));
677 m.insert(
678 "topicId".to_owned(),
679 ::serde_json::Value::String("AAAAAAAAAAAAAAAAAAAAAA".to_owned()),
680 );
681 m.insert("replicas".to_owned(), ::serde_json::Value::Array(vec![]));
682 m.insert("isr".to_owned(), ::serde_json::Value::Array(vec![]));
683 m.insert(
684 "removingReplicas".to_owned(),
685 ::serde_json::Value::Array(vec![]),
686 );
687 m.insert(
688 "addingReplicas".to_owned(),
689 ::serde_json::Value::Array(vec![]),
690 );
691 m.insert("leader".to_owned(), ::serde_json::json!(-1));
692 m.insert("leaderRecoveryState".to_owned(), ::serde_json::json!(1));
693 m.insert("leaderEpoch".to_owned(), ::serde_json::json!(-1));
694 m.insert("partitionEpoch".to_owned(), ::serde_json::json!(-1));
695 if version >= 1 {
696 m.insert("directories".to_owned(), ::serde_json::Value::Array(vec![]));
697 }
698 if version == 2 {
699 m.insert(
700 "eligibleLeaderReplicas".to_owned(),
701 ::serde_json::Value::Array(vec![::serde_json::json!(1)]),
702 );
703 }
704 if version == 2 {
705 m.insert(
706 "lastKnownElr".to_owned(),
707 ::serde_json::Value::Array(vec![::serde_json::json!(1)]),
708 );
709 }
710 ::serde_json::Value::Object(m)
711}