mqute_codec/protocol/v5/packet.rs
1//! # MQTT v5 Packet Enumeration
2//!
3//! This module provides a unified `Packet` enum that represents all possible MQTT v5 packet types.
4//! It serves as the primary interface for decoding and encoding MQTT packets, handling the complete
5//! protocol specification including all control packet types.
6
7use crate::Error;
8use crate::codec::{Decode, Encode, RawPacket};
9use crate::protocol::PacketType;
10use crate::protocol::v5::{
11 Auth, ConnAck, Connect, Disconnect, PingReq, PingResp, PubAck, PubComp, PubRec, PubRel,
12 Publish, SubAck, Subscribe, UnsubAck, Unsubscribe,
13};
14
15/// Represents all possible MQTT v5 packet types
16///
17/// This enum serves as the main abstraction for working with MQTT packets,
18/// providing a unified interface for packet handling while maintaining
19/// type safety for each specific packet type.
20///
21/// # Example
22///
23/// ```rust
24/// use mqute_codec::protocol::v5::Packet;
25/// use mqute_codec::protocol::v5::{Connect, ConnectProperties};
26/// use bytes::{Bytes, BytesMut};
27///
28/// let properties = ConnectProperties {
29/// session_expiry_interval: Some(3600),
30/// ..Default::default()
31/// };
32///
33/// let connect = Connect::with_properties(
34/// "client",
35/// None,
36/// None,
37/// properties.clone(),
38/// 30,
39/// true);
40///
41/// let mut buf = BytesMut::new();
42///
43/// let packet = Packet::Connect(connect);
44///
45/// packet.encode(&mut buf).unwrap()
46/// ```
47#[derive(Debug, Clone, PartialEq, Eq)]
48pub enum Packet {
49 /// Client-initiated connection request. First packet in connection establishment flow
50 Connect(Connect),
51
52 /// Server connection acknowledgment. Sent in response to CONNECT packet
53 ConnAck(ConnAck),
54
55 /// Message publication. Primary message delivery mechanism.
56 Publish(Publish),
57
58 /// QoS 1 publication acknowledgment. Acknowledges receipt of QoS 1 messages
59 PubAck(PubAck),
60
61 /// QoS 2 publication received (part 1). First packet in QoS 2 protocol flow
62 PubRec(PubRec),
63
64 /// QoS 2 publication release (part 2). Second packet in QoS 2 protocol flow
65 PubRel(PubRel),
66
67 /// QoS 2 publication complete (part 3). Final packet in QoS 2 protocol flow
68 PubComp(PubComp),
69
70 /// Subscription request. Begins subscription creation/modification
71 Subscribe(Subscribe),
72
73 /// Subscription acknowledgment. Confirms subscription processing results
74 SubAck(SubAck),
75
76 /// Unsubscription request. Begins subscription termination
77 Unsubscribe(Unsubscribe),
78
79 /// Unsubscription acknowledgment. Confirms unsubscription processing
80 UnsubAck(UnsubAck),
81
82 /// Keep-alive ping request. Must be responded to with PINGRESP
83 PingReq(PingReq),
84
85 /// Keep-alive ping response. Sent in response to PINGREQ to confirm connection is active
86 PingResp(PingResp),
87
88 /// Graceful connection termination. Properly closes the MQTT connection
89 Disconnect(Disconnect),
90
91 /// Authentication exchange. Used for extended authentication flows
92 Auth(Auth),
93}
94
95impl Packet {
96 /// Decodes a raw MQTT packet into the appropriate Packet variant
97 ///
98 /// This is the primary entry point for packet processing, handling:
99 /// - Packet type identification
100 /// - Payload validation
101 /// - Special cases for empty payload packets
102 /// - Delegation to specific packet decoders
103 pub fn decode(raw_packet: RawPacket) -> Result<Self, Error> {
104 let packet_type = raw_packet.header.packet_type();
105
106 // Handle packets that may have empty payloads
107 if raw_packet.header.remaining_len() == 0 {
108 return match packet_type {
109 PacketType::PingReq => Ok(Self::PingReq(PingReq::decode(raw_packet)?)),
110 PacketType::PingResp => Ok(Self::PingResp(PingResp::decode(raw_packet)?)),
111 PacketType::Disconnect => Ok(Self::Disconnect(Disconnect::decode(raw_packet)?)),
112 PacketType::Auth => Ok(Self::Auth(Auth::decode(raw_packet)?)),
113 _ => Err(Error::PayloadRequired),
114 };
115 }
116
117 // Dispatch to appropriate packet decoder
118 let decoded = match packet_type {
119 PacketType::Connect => Self::Connect(Connect::decode(raw_packet)?),
120 PacketType::ConnAck => Self::ConnAck(ConnAck::decode(raw_packet)?),
121 PacketType::Publish => Self::Publish(Publish::decode(raw_packet)?),
122 PacketType::PubAck => Self::PubAck(PubAck::decode(raw_packet)?),
123 PacketType::PubRec => Self::PubRec(PubRec::decode(raw_packet)?),
124 PacketType::PubRel => Self::PubRel(PubRel::decode(raw_packet)?),
125 PacketType::PubComp => Self::PubComp(PubComp::decode(raw_packet)?),
126 PacketType::Subscribe => Self::Subscribe(Subscribe::decode(raw_packet)?),
127 PacketType::SubAck => Self::SubAck(SubAck::decode(raw_packet)?),
128 PacketType::Unsubscribe => Self::Unsubscribe(Unsubscribe::decode(raw_packet)?),
129 PacketType::UnsubAck => Self::UnsubAck(UnsubAck::decode(raw_packet)?),
130 PacketType::Disconnect => Self::Disconnect(Disconnect::decode(raw_packet)?),
131 PacketType::Auth => Self::Auth(Auth::decode(raw_packet)?),
132 // Ping packets should have been handled above
133 _ => return Err(Error::MalformedPacket),
134 };
135
136 Ok(decoded)
137 }
138
139 /// Encodes the packet into its wire format
140 ///
141 /// Delegates to the specific packet implementation's encoder while
142 /// providing a unified interface for all packet types.
143 pub fn encode(&self, buf: &mut bytes::BytesMut) -> Result<(), Error> {
144 match self {
145 Self::Connect(packet) => packet.encode(buf),
146 Self::ConnAck(packet) => packet.encode(buf),
147 Self::Publish(packet) => packet.encode(buf),
148 Self::PubAck(packet) => packet.encode(buf),
149 Self::PubRec(packet) => packet.encode(buf),
150 Self::PubRel(packet) => packet.encode(buf),
151 Self::PubComp(packet) => packet.encode(buf),
152 Self::Subscribe(packet) => packet.encode(buf),
153 Self::SubAck(packet) => packet.encode(buf),
154 Self::Unsubscribe(packet) => packet.encode(buf),
155 Self::UnsubAck(packet) => packet.encode(buf),
156 Self::PingReq(packet) => packet.encode(buf),
157 Self::PingResp(packet) => packet.encode(buf),
158 Self::Disconnect(packet) => packet.encode(buf),
159 Self::Auth(packet) => packet.encode(buf),
160 }
161 }
162}