1use crate::codec::{Decoder, Encoder};
2use crate::error::Result;
3use crate::header::RequestHeader;
4
5pub const API_KEY: i16 = 37;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct CreatePartitionsRequestV0 {
9 pub correlation_id: i32,
10 pub client_id: Option<String>,
11 pub topics: Vec<CreatePartitionsTopicV0>,
12 pub timeout_ms: i32,
13 pub validate_only: bool,
14}
15
16impl CreatePartitionsRequestV0 {
17 pub fn encode(&self) -> Result<Vec<u8>> {
18 let mut encoder = Encoder::new();
19 RequestHeader {
20 api_key: API_KEY,
21 api_version: 0,
22 correlation_id: self.correlation_id,
23 client_id: self.client_id.clone(),
24 }
25 .encode_v1(&mut encoder)?;
26 encoder.write_array(Some(&self.topics), |encoder, topic| topic.encode(encoder))?;
27 encoder.write_i32(self.timeout_ms);
28 encoder.write_bool(self.validate_only);
29 Ok(encoder.into_bytes())
30 }
31}
32
33#[derive(Debug, Clone, PartialEq, Eq)]
34pub struct CreatePartitionsTopicV0 {
35 pub name: String,
36 pub count: i32,
37 pub assignments: Option<Vec<CreatePartitionsAssignmentV0>>,
38}
39
40impl CreatePartitionsTopicV0 {
41 fn encode(&self, encoder: &mut Encoder) -> Result<()> {
42 encoder.write_string(&self.name)?;
43 encoder.write_i32(self.count);
44 encoder.write_array(self.assignments.as_deref(), |encoder, assignment| {
45 encoder.write_array(Some(&assignment.broker_ids), |encoder, broker_id| {
46 encoder.write_i32(*broker_id);
47 Ok(())
48 })
49 })
50 }
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
54pub struct CreatePartitionsAssignmentV0 {
55 pub broker_ids: Vec<i32>,
56}
57
58#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct CreatePartitionsResponseV0 {
60 pub throttle_time_ms: i32,
61 pub results: Vec<CreatePartitionsTopicResultV0>,
62}
63
64impl CreatePartitionsResponseV0 {
65 pub fn decode_body(decoder: &mut Decoder<'_>) -> Result<Self> {
66 Ok(Self {
67 throttle_time_ms: decoder.read_i32()?,
68 results: decoder
69 .read_array(
70 "create partitions results",
71 CreatePartitionsTopicResultV0::decode,
72 )?
73 .unwrap_or_default(),
74 })
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub struct CreatePartitionsTopicResultV0 {
80 pub name: String,
81 pub error_code: i16,
82 pub error_message: Option<String>,
83}
84
85impl CreatePartitionsTopicResultV0 {
86 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
87 Ok(Self {
88 name: decoder.read_string()?,
89 error_code: decoder.read_i16()?,
90 error_message: decoder.read_nullable_string()?,
91 })
92 }
93}
94
95#[cfg(test)]
96#[allow(clippy::unwrap_used)]
97mod tests {
98 use super::*;
99
100 #[test]
101 fn encodes_create_partitions_v0_request() {
102 let request = CreatePartitionsRequestV0 {
103 correlation_id: 9,
104 client_id: Some("kafrust".to_owned()),
105 topics: vec![
106 CreatePartitionsTopicV0 {
107 name: "orders".to_owned(),
108 count: 4,
109 assignments: None,
110 },
111 CreatePartitionsTopicV0 {
112 name: "payments".to_owned(),
113 count: 3,
114 assignments: Some(vec![CreatePartitionsAssignmentV0 {
115 broker_ids: vec![1, 2],
116 }]),
117 },
118 ],
119 timeout_ms: 30_000,
120 validate_only: true,
121 };
122
123 assert_eq!(
124 request.encode().unwrap(),
125 [
126 0, 37, 0, 0, 0, 0, 0, 9, 0, 7, b'k', b'a', b'f', b'r', b'u', b's', b't', 0, 0, 0, 2, 0, 6, b'o', b'r', b'd', b'e', b'r', b's', 0, 0, 0, 4, 0xff, 0xff, 0xff, 0xff, 0, 8, b'p', b'a', b'y', b'm', b'e', b'n', b't', b's', 0, 0, 0, 3, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 117, 48, 1, ]
143 );
144 assert_eq!(API_KEY, 37);
145 }
146
147 #[test]
148 fn decodes_create_partitions_v0_response() {
149 let bytes = [
150 0, 0, 0, 12, 0, 0, 0, 2, 0, 6, b'o', b'r', b'd', b'e', b'r', b's', 0, 0, 0xff, 0xff, 0, 8, b'p', b'a', b'y', b'm', b'e', b'n', b't', b's', 0, 37, 0, 7, b'i', b'n', b'v', b'a', b'l', b'i', b'd', ];
159 let mut decoder = Decoder::new(&bytes);
160
161 let response = CreatePartitionsResponseV0::decode_body(&mut decoder).unwrap();
162
163 assert_eq!(response.throttle_time_ms, 12);
164 assert_eq!(response.results.len(), 2);
165 assert_eq!(response.results[0].name, "orders");
166 assert_eq!(response.results[0].error_code, 0);
167 assert_eq!(response.results[1].error_code, 37);
168 assert_eq!(
169 response.results[1].error_message.as_deref(),
170 Some("invalid")
171 );
172 assert!(decoder.is_empty());
173 }
174}