1use crate::anyvec::AnyVec;
4use crate::coding::encoder::{BytesIter, OptionalBytesIter, PacketLenIter, U16Iter, U8Iter, Unit};
5use crate::coding::length::Length;
6use crate::coding::{Decoder, Encoder};
7use crate::err;
8use crate::error::{Data, DecoderError, MemoryError};
9use crate::packets::TryFromIterator;
10use core::iter::Chain;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct Connect<Bytes> {
15 keep_alive_secs: u16,
17 clean_session: bool,
19 will_retain: bool,
21 will_qos: u8,
29 client_id: Bytes,
35 will_topic: Option<Bytes>,
37 will_message: Option<Bytes>,
39 username: Option<Bytes>,
41 password: Option<Bytes>,
43}
44impl<Bytes> Connect<Bytes>
45where
46 Bytes: AnyVec<u8>,
47{
48 pub const TYPE: u8 = 1;
50
51 const PROTOCOL_NAME: [u8; 6] = *b"\x00\x04MQTT";
53 const PROTOCOL_LEVEL_MQTT_3_1_1: u8 = 0x04;
55
56 pub fn new<T>(keep_alive_secs: u16, clean_session: bool, client_id: T) -> Result<Self, MemoryError>
58 where
59 T: AsRef<[u8]>,
60 {
61 let client_id = Bytes::new(client_id.as_ref())?;
62 Ok(Self {
63 keep_alive_secs,
64 clean_session,
65 will_retain: false,
66 will_qos: 0,
67 client_id,
68 will_topic: None,
69 will_message: None,
70 username: None,
71 password: None,
72 })
73 }
74 pub fn with_will<T, M>(mut self, topic: T, message: M, qos: u8, retain: bool) -> Result<Self, MemoryError>
82 where
83 T: AsRef<[u8]>,
84 M: AsRef<[u8]>,
85 {
86 self.will_topic = Bytes::new(topic.as_ref()).map(Some)?;
87 self.will_message = Bytes::new(message.as_ref()).map(Some)?;
88 self.will_retain = retain;
89 self.will_qos = qos;
90 Ok(self)
91 }
92 pub fn with_username_password<U, P>(mut self, username: U, password: P) -> Result<Self, MemoryError>
94 where
95 U: AsRef<[u8]>,
96 P: AsRef<[u8]>,
97 {
98 self.username = Bytes::new(username.as_ref()).map(Some)?;
99 self.password = Bytes::new(password.as_ref()).map(Some)?;
100 Ok(self)
101 }
102
103 pub const fn keep_alive_secs(&self) -> u16 {
105 self.keep_alive_secs
106 }
107
108 pub const fn clean_session(&self) -> bool {
111 self.clean_session
112 }
113
114 pub fn client_id(&self) -> &[u8] {
120 self.client_id.as_ref()
121 }
122
123 pub const fn will_retain(&self) -> bool {
125 self.will_retain
126 }
127 pub const fn will_qos(&self) -> u8 {
129 self.will_qos
130 }
131 pub fn will_topic(&self) -> Option<&[u8]> {
133 self.will_topic.as_ref().map(|bytes| bytes.as_ref())
134 }
135 pub fn will_message(&self) -> Option<&[u8]> {
137 self.will_message.as_ref().map(|bytes| bytes.as_ref())
138 }
139
140 pub fn username(&self) -> Option<&[u8]> {
142 self.username.as_ref().map(|bytes| bytes.as_ref())
143 }
144 pub fn password(&self) -> Option<&[u8]> {
146 self.password.as_ref().map(|bytes| bytes.as_ref())
147 }
148}
149impl<Bytes> TryFromIterator for Connect<Bytes>
150where
151 Bytes: AnyVec<u8>,
152{
153 fn try_from_iter<T>(iter: T) -> Result<Self, DecoderError>
154 where
155 T: IntoIterator<Item = u8>,
156 {
157 let mut decoder = Decoder::new(iter);
170 let (Self::TYPE, _flags) = decoder.header()? else {
171 return Err(err!(Data::SpecViolation, "invalid packet type"))?;
172 };
173
174 let len = decoder.packetlen()?;
176 let mut decoder = decoder.limit(len);
177
178 let Self::PROTOCOL_NAME = decoder.raw()? else {
180 return Err(err!(Data::SpecViolation, "invalid protocol name"))?;
181 };
182 let Self::PROTOCOL_LEVEL_MQTT_3_1_1 = decoder.u8()? else {
183 return Err(err!(Data::SpecViolation, "invalid protocol version"))?;
184 };
185
186 let [f_user, f_pass, will_retain, will_qos0, will_qos1, f_will, clean_session, _] = decoder.bitmap()?;
188 let keep_alive_secs = decoder.u16()?;
189 let client_id = decoder.bytes()?;
190 let will_topic = decoder.optional_bytes(f_will)?;
191 let will_message = decoder.optional_bytes(f_will)?;
192 let username = decoder.optional_bytes(f_user)?;
193 let password = decoder.optional_bytes(f_pass)?;
194
195 let will_qos = ((will_qos0 as u8) << 1) | (will_qos1 as u8);
197 Ok(Self {
198 keep_alive_secs,
199 clean_session,
200 will_retain,
201 will_qos,
202 client_id,
203 will_topic,
204 will_message,
205 username,
206 password,
207 })
208 }
209}
210impl<Bytes> IntoIterator for Connect<Bytes>
211where
212 Bytes: AnyVec<u8>,
213{
214 type Item = u8;
215 #[rustfmt::skip]
216 type IntoIter =
217 Chain<Chain<Chain<Chain<Chain<Chain<Chain<Chain<Chain<Chain<Chain<
219 Unit, U8Iter>,
221 PacketLenIter>,
223 <[u8; 6] as IntoIterator>::IntoIter>,
225 U8Iter>,
227 U8Iter>,
229 U16Iter>,
231 BytesIter<Bytes>>,
233 OptionalBytesIter<Bytes>>,
235 OptionalBytesIter<Bytes>>,
237 OptionalBytesIter<Bytes>>,
239 OptionalBytesIter<Bytes>>;
241
242 fn into_iter(self) -> Self::IntoIter {
243 let flags = [
245 self.username.is_some(),
246 self.password.is_some(),
247 self.will_retain,
248 (self.will_qos >> 1) != 0,
249 (self.will_qos & 1) != 0,
250 self.will_topic.is_some(),
251 self.clean_session,
252 false,
253 ];
254
255 let len = Length::new()
266 .raw(&Self::PROTOCOL_NAME)
267 .u8(&Self::PROTOCOL_LEVEL_MQTT_3_1_1)
268 .bitmap(&flags)
269 .u16(&self.keep_alive_secs)
270 .bytes(&self.client_id)
271 .optional_bytes(&self.will_topic)
272 .optional_bytes(&self.will_message)
273 .optional_bytes(&self.username)
274 .optional_bytes(&self.password)
275 .into();
276
277 Encoder::default()
290 .header(Self::TYPE, [false, false, false, false])
291 .packetlen(len)
292 .raw(Self::PROTOCOL_NAME)
293 .u8(Self::PROTOCOL_LEVEL_MQTT_3_1_1)
294 .bitmap(flags)
295 .u16(self.keep_alive_secs)
296 .bytes(self.client_id)
297 .optional_bytes(self.will_topic)
298 .optional_bytes(self.will_message)
299 .optional_bytes(self.username)
300 .optional_bytes(self.password)
301 .into_iter()
302 }
303}