iggy_binary_protocol/responses/consumer_groups/
sync_consumer_group.rs1use crate::WireError;
19use crate::codec::{WireDecode, WireEncode, bounded_capacity, read_u32_le, read_u64_le};
20use bytes::{BufMut, BytesMut};
21
22#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct SyncConsumerGroupResponse {
31 pub generation: u64,
32 pub partitions: Vec<u32>,
33}
34
35impl WireEncode for SyncConsumerGroupResponse {
36 fn encoded_size(&self) -> usize {
37 8 + 4 + self.partitions.len() * 4
38 }
39
40 #[allow(clippy::cast_possible_truncation)]
41 fn encode(&self, buf: &mut BytesMut) {
42 buf.put_u64_le(self.generation);
43 buf.put_u32_le(self.partitions.len() as u32);
44 for &partition_id in &self.partitions {
45 buf.put_u32_le(partition_id);
46 }
47 }
48}
49
50impl WireDecode for SyncConsumerGroupResponse {
51 fn decode(buf: &[u8]) -> Result<(Self, usize), WireError> {
52 let generation = read_u64_le(buf, 0)?;
53 let partitions_count = read_u32_le(buf, 8)?;
54 let remaining = buf.len().saturating_sub(12);
55 let mut partitions =
56 Vec::with_capacity(bounded_capacity(partitions_count as usize, remaining, 4));
57 let mut offset = 12;
58 for _ in 0..partitions_count {
59 partitions.push(read_u32_le(buf, offset)?);
60 offset += 4;
61 }
62 Ok((
63 Self {
64 generation,
65 partitions,
66 },
67 offset,
68 ))
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 #[test]
77 fn roundtrip() {
78 let response = SyncConsumerGroupResponse {
79 generation: 7,
80 partitions: vec![0, 2, 4],
81 };
82 let bytes = response.to_bytes();
83 let (decoded, consumed) = SyncConsumerGroupResponse::decode(&bytes).unwrap();
84 assert_eq!(consumed, bytes.len());
85 assert_eq!(decoded, response);
86 }
87
88 #[test]
89 fn roundtrip_empty_assignment() {
90 let response = SyncConsumerGroupResponse {
91 generation: 1,
92 partitions: vec![],
93 };
94 let bytes = response.to_bytes();
95 let (decoded, consumed) = SyncConsumerGroupResponse::decode(&bytes).unwrap();
96 assert_eq!(consumed, bytes.len());
97 assert_eq!(decoded, response);
98 }
99
100 #[test]
101 fn truncated_returns_error() {
102 let response = SyncConsumerGroupResponse {
103 generation: 7,
104 partitions: vec![1, 2],
105 };
106 let bytes = response.to_bytes();
107 for i in 0..bytes.len() {
108 assert!(
109 SyncConsumerGroupResponse::decode(&bytes[..i]).is_err(),
110 "expected error for truncation at byte {i}"
111 );
112 }
113 }
114}