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}