mqute_codec/protocol/header.rs
1//! # MQTT Protocol - Fixed Header and Flags
2//!
3//! This module provides structures and utilities for handling the fixed header and flags
4//! in the MQTT protocol.
5//!
6//! The MQTT protocol uses a fixed header to describe the type of packet and its properties.
7//! The `FixedHeader` struct represents this header, while the `Flags` struct encapsulates
8//! the control flags (DUP, QoS, and RETAIN) associated with the packet.
9
10use crate::codec;
11use crate::protocol::util;
12use crate::protocol::{PacketType, QoS};
13use crate::Error;
14use bytes::{Buf, BufMut, BytesMut};
15use std::cmp::PartialEq;
16
17/// Represents the control flags in an MQTT packet.
18///
19/// # Examples
20///
21/// ```rust
22/// use mqute_codec::protocol::QoS;
23/// use mqute_codec::protocol::Flags;
24///
25/// // Create default flags
26/// let default_flags = Flags::default();
27/// assert_eq!(default_flags.dup, false);
28/// assert_eq!(default_flags.qos, QoS::AtMostOnce);
29/// assert_eq!(default_flags.retain, false);
30///
31/// // Create custom flags
32/// let custom_flags = Flags::new(QoS::AtLeastOnce);
33/// assert_eq!(custom_flags.qos, QoS::AtLeastOnce);
34/// ```
35#[derive(Debug, Copy, Clone, PartialEq, Eq)]
36pub struct Flags {
37 /// Indicates if the packet is a duplicate.
38 pub dup: bool,
39
40 /// The Quality of Service level (0, 1, or 2).
41 pub qos: QoS,
42
43 /// Indicates if the message should be retained by the broker.
44 pub retain: bool,
45}
46
47impl Default for Flags {
48 /// Creates default `Flags` with:
49 /// - `dup`: `false`
50 /// - `qos`: `QoS::AtMostOnce`
51 /// - `retain`: `false`
52 fn default() -> Self {
53 Flags {
54 dup: false,
55 qos: QoS::AtMostOnce,
56 retain: false,
57 }
58 }
59}
60
61impl Flags {
62 /// Creates new `Flags` with the specified QoS level.
63 ///
64 /// # Examples
65 ///
66 /// ```rust
67 /// use mqute_codec::protocol::QoS;
68 /// use mqute_codec::protocol::Flags;
69 ///
70 /// let flags = Flags::new(QoS::ExactlyOnce);
71 /// assert_eq!(flags.qos, QoS::ExactlyOnce);
72 /// ```
73 pub fn new(qos: QoS) -> Self {
74 Flags {
75 dup: false,
76 qos,
77 retain: false,
78 }
79 }
80
81 /// Checks if the flags are set to their default values.
82 ///
83 /// # Examples
84 ///
85 /// ```rust
86 /// use mqute_codec::protocol::Flags;
87 ///
88 /// let flags = Flags::default();
89 /// assert!(flags.is_default());
90 /// ```
91 pub fn is_default(&self) -> bool {
92 *self == Self::default()
93 }
94}
95
96/// Represents the fixed header of an MQTT packet.
97///
98/// # Examples
99///
100/// ```
101/// use mqute_codec::protocol::{FixedHeader, PacketType};
102///
103/// // Create a fixed header for a CONNECT packet
104/// let header = FixedHeader::new(PacketType::Connect, 10);
105/// assert_eq!(header.packet_type(), PacketType::Connect);
106/// assert_eq!(header.remaining_len(), 10);
107/// ```
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub struct FixedHeader {
110 /// The first byte of the packet, encoding the packet type and flags.
111 control_byte: u8,
112
113 /// The length of the remaining payload.
114 remaining_len: usize,
115}
116
117impl FixedHeader {
118 /// Creates a new `FixedHeader` with the specified packet type and remaining length.
119 ///
120 /// # Examples
121 ///
122 /// ```
123 /// use mqute_codec::protocol::{FixedHeader, PacketType};
124 ///
125 /// let header = FixedHeader::new(PacketType::Publish, 20);
126 /// assert_eq!(header.packet_type(), PacketType::Publish);
127 /// ```
128 pub fn new(packet: PacketType, remaining_len: usize) -> Self {
129 let control_byte = build_control_byte(packet, Flags::default());
130
131 FixedHeader {
132 control_byte,
133 remaining_len,
134 }
135 }
136
137 /// Attempts to create a `FixedHeader` from a control byte and remaining length.
138 ///
139 /// # Errors
140 /// Returns an error if the packet type is invalid.
141 ///
142 /// # Examples
143 ///
144 /// ```
145 /// use mqute_codec::protocol::{FixedHeader, PacketType};
146 /// use mqute_codec::Error;
147 ///
148 /// let header = FixedHeader::try_from(0x30, 10).unwrap();
149 /// assert_eq!(header.packet_type(), PacketType::Publish);
150 /// ```
151 pub fn try_from(control_byte: u8, remaining_len: usize) -> Result<Self, Error> {
152 let _: PacketType = fetch_packet_type(control_byte).try_into()?;
153
154 Ok(FixedHeader {
155 control_byte,
156 remaining_len,
157 })
158 }
159
160 /// Creates a `FixedHeader` with custom flags.
161 ///
162 /// # Examples
163 ///
164 /// ```
165 /// use mqute_codec::protocol::{FixedHeader, PacketType, Flags};
166 /// use mqute_codec::protocol::QoS;
167 ///
168 /// let flags = Flags::new(QoS::AtLeastOnce);
169 /// let header = FixedHeader::with_flags(PacketType::Publish, flags, 15);
170 /// assert_eq!(header.flags().qos, QoS::AtLeastOnce);
171 /// ```
172 pub fn with_flags(packet_type: PacketType, flags: Flags, remaining_len: usize) -> Self {
173 let control_byte = build_control_byte(packet_type, flags);
174 FixedHeader {
175 control_byte,
176 remaining_len,
177 }
178 }
179
180 /// Returns the packet type encoded in the control byte.
181 ///
182 /// # Examples
183 ///
184 /// ```
185 /// use mqute_codec::protocol::{FixedHeader, PacketType};
186 ///
187 /// let header = FixedHeader::new(PacketType::Subscribe, 5);
188 /// assert_eq!(header.packet_type(), PacketType::Subscribe);
189 /// ```
190 pub fn packet_type(&self) -> PacketType {
191 fetch_packet_type(self.control_byte).try_into().unwrap()
192 }
193
194 /// Extracts and returns the flags from the control byte.
195 ///
196 /// # Examples
197 ///
198 /// ```
199 /// use mqute_codec::protocol::{FixedHeader, PacketType, Flags};
200 /// use mqute_codec::protocol::QoS;
201 ///
202 /// let header = FixedHeader::new(PacketType::Publish, 10);
203 /// let flags = header.flags();
204 /// assert_eq!(flags.qos, QoS::AtMostOnce);
205 /// ```
206 pub fn flags(&self) -> Flags {
207 let flags = self.control_byte & 0x0F;
208 let dup: bool = (flags & 0x08) != 0;
209 let qos = ((flags >> 1) & 0x03).try_into().unwrap();
210 let retain = flags & 0x01 != 0;
211
212 Flags { dup, qos, retain }
213 }
214
215 /// Returns the remaining length of the payload.
216 ///
217 /// # Examples
218 ///
219 /// ```
220 /// use mqute_codec::protocol::{FixedHeader, PacketType};
221 ///
222 /// let header = FixedHeader::new(PacketType::Publish, 25);
223 /// assert_eq!(header.remaining_len(), 25);
224 /// ```
225 pub fn remaining_len(&self) -> usize {
226 self.remaining_len
227 }
228
229 /// Returns the length of the fixed header in bytes.
230 ///
231 /// # Examples
232 ///
233 /// ```
234 /// use mqute_codec::protocol::{FixedHeader, PacketType};
235 ///
236 /// let header = FixedHeader::new(PacketType::Publish, 10);
237 /// assert_eq!(header.fixed_len(), 2); // 1 byte for control byte, 1 byte for remaining length
238 /// ```
239 pub fn fixed_len(&self) -> usize {
240 util::len_bytes(self.remaining_len) + 1
241 }
242
243 /// Returns the total length of the packet (fixed header + payload).
244 ///
245 /// # Examples
246 ///
247 /// ```
248 /// use mqute_codec::protocol::{FixedHeader, PacketType};
249 ///
250 /// let header = FixedHeader::new(PacketType::Publish, 10);
251 /// assert_eq!(header.packet_len(), 12); // 2 bytes for fixed header, 10 bytes for payload
252 /// ```
253 pub fn packet_len(&self) -> usize {
254 self.remaining_len + self.fixed_len()
255 }
256
257 /// Encodes the fixed header into a buffer.
258 ///
259 /// # Errors
260 /// Returns an error if encoding fails.
261 ///
262 /// # Examples
263 ///
264 /// ```
265 /// use mqute_codec::protocol::{FixedHeader, PacketType};
266 /// use bytes::BytesMut;
267 ///
268 /// let mut buf = BytesMut::new();
269 /// let header = FixedHeader::new(PacketType::Publish, 10);
270 /// header.encode(&mut buf).unwrap();
271 /// ```
272 pub fn encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
273 buf.put_u8(self.control_byte);
274 codec::util::encode_variable_integer(buf, self.remaining_len as u32)
275 }
276
277 /// Decodes a fixed header from a buffer.
278 ///
279 /// # Errors
280 /// Returns an error if decoding fails or the payload size exceeds the limit.
281 ///
282 /// # Examples
283 ///
284 /// ```
285 /// use mqute_codec::protocol::{FixedHeader, PacketType};
286 /// use bytes::BytesMut;
287 ///
288 /// let mut buf = BytesMut::from(&[0x30, 0x04,
289 /// 0x00, 0x00,
290 /// 0x00, 0x00][..]); // Publish packet with remaining length 4
291 /// let header = FixedHeader::decode(&buf, None).unwrap();
292 /// assert_eq!(header.packet_type(), PacketType::Publish);
293 /// assert_eq!(header.remaining_len(), 4);
294 /// ```
295 pub fn decode(buf: &[u8], inbound_max_size: Option<usize>) -> Result<Self, Error> {
296 let buf_len = buf.len();
297 if buf_len < 2 {
298 return Err(Error::NotEnoughBytes(2 - buf_len));
299 }
300
301 let mut buf = buf;
302 let control_byte = buf.get_u8();
303 let remaining_len = codec::util::decode_variable_integer(buf)? as usize;
304
305 let header = FixedHeader::try_from(control_byte, remaining_len)?;
306
307 if let Some(max_size) = inbound_max_size {
308 if header.remaining_len > max_size {
309 return Err(Error::PayloadSizeLimitExceeded(header.remaining_len));
310 }
311 }
312
313 let packet_len = header.packet_len();
314 if buf_len < packet_len {
315 return Err(Error::NotEnoughBytes(packet_len - buf_len));
316 }
317
318 Ok(header)
319 }
320}
321
322/// Extracts the packet type from the control byte.
323#[inline]
324fn fetch_packet_type(control_byte: u8) -> u8 {
325 control_byte >> 4
326}
327
328/// Builds the control byte from the packet type and flags.
329const fn build_control_byte(packet_type: PacketType, flags: Flags) -> u8 {
330 let byte = (packet_type as u8) << 4;
331 let flags = (flags.dup as u8) << 3 | (flags.qos as u8) << 1 | (flags.retain as u8);
332 byte | flags
333}