mqtt_protocol_core/mqtt/packet/
kind.rs

1// MIT License
2//
3// Copyright (c) 2025 Takatoshi Kondo
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23/// Trait for compile-time packet classification and type introspection
24///
25/// `PacketKind` provides a way to classify MQTT packet types at compile time using
26/// constant boolean flags. This enables efficient type-based dispatch and filtering
27/// without runtime overhead. Each MQTT packet type implements this trait with
28/// appropriate flags set to `true`.
29///
30/// The trait includes flags for:
31/// - **Packet types**: CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP,
32///   SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, PINGREQ, PINGRESP, DISCONNECT, AUTH
33/// - **Protocol versions**: V3_1_1, V5_0
34///
35/// # Examples
36///
37/// ```ignore
38/// use mqtt_protocol_core::mqtt::packet::PacketKind;
39/// use mqtt_protocol_core::mqtt::packet::v5_0::Connect;
40///
41/// // Check packet type at compile time
42/// if Connect::IS_CONNECT {
43///     println!("This is a CONNECT packet");
44/// }
45///
46/// // Check protocol version
47/// if Connect::IS_V5_0 {
48///     println!("This is a v5.0 packet");
49/// }
50/// ```
51pub trait PacketKind {
52    /// `true` if this is a CONNECT packet
53    const IS_CONNECT: bool = false;
54    /// `true` if this is a CONNACK packet
55    const IS_CONNACK: bool = false;
56    /// `true` if this is a PUBLISH packet
57    const IS_PUBLISH: bool = false;
58    /// `true` if this is a PUBACK packet
59    const IS_PUBACK: bool = false;
60    /// `true` if this is a PUBREC packet
61    const IS_PUBREC: bool = false;
62    /// `true` if this is a PUBREL packet
63    const IS_PUBREL: bool = false;
64    /// `true` if this is a PUBCOMP packet
65    const IS_PUBCOMP: bool = false;
66    /// `true` if this is a SUBSCRIBE packet
67    const IS_SUBSCRIBE: bool = false;
68    /// `true` if this is a SUBACK packet
69    const IS_SUBACK: bool = false;
70    /// `true` if this is an UNSUBSCRIBE packet
71    const IS_UNSUBSCRIBE: bool = false;
72    /// `true` if this is an UNSUBACK packet
73    const IS_UNSUBACK: bool = false;
74    /// `true` if this is a PINGREQ packet
75    const IS_PINGREQ: bool = false;
76    /// `true` if this is a PINGRESP packet
77    const IS_PINGRESP: bool = false;
78    /// `true` if this is a DISCONNECT packet
79    const IS_DISCONNECT: bool = false;
80    /// `true` if this is an AUTH packet (v5.0 only)
81    const IS_AUTH: bool = false;
82    /// `true` if this is an MQTT v3.1.1 packet
83    const IS_V3_1_1: bool = false;
84    /// `true` if this is an MQTT v5.0 packet
85    const IS_V5_0: bool = false;
86}
87
88// MQTT v3.1.1 and v5.0 packet implementations
89
90/// `PacketKind` implementation for v3.1.1 CONNECT packet
91impl PacketKind for crate::mqtt::packet::v3_1_1::Connect {
92    const IS_CONNECT: bool = true;
93    const IS_V3_1_1: bool = true;
94}
95
96/// `PacketKind` implementation for v3.1.1 CONNACK packet
97impl PacketKind for crate::mqtt::packet::v3_1_1::Connack {
98    const IS_CONNACK: bool = true;
99    const IS_V3_1_1: bool = true;
100}
101
102/// `PacketKind` implementation for v5.0 CONNECT packet
103impl PacketKind for crate::mqtt::packet::v5_0::Connect {
104    const IS_CONNECT: bool = true;
105    const IS_V5_0: bool = true;
106}
107
108/// `PacketKind` implementation for v5.0 CONNACK packet
109impl PacketKind for crate::mqtt::packet::v5_0::Connack {
110    const IS_CONNACK: bool = true;
111    const IS_V5_0: bool = true;
112}
113
114// Additional v3.1.1 packet implementations
115
116/// `PacketKind` implementation for v3.1.1 PINGREQ packet
117impl PacketKind for crate::mqtt::packet::v3_1_1::Pingreq {
118    const IS_PINGREQ: bool = true;
119    const IS_V3_1_1: bool = true;
120}
121
122/// `PacketKind` implementation for v3.1.1 PINGRESP packet
123impl PacketKind for crate::mqtt::packet::v3_1_1::Pingresp {
124    const IS_PINGRESP: bool = true;
125    const IS_V3_1_1: bool = true;
126}
127
128/// `PacketKind` implementation for v3.1.1 DISCONNECT packet
129impl PacketKind for crate::mqtt::packet::v3_1_1::Disconnect {
130    const IS_DISCONNECT: bool = true;
131    const IS_V3_1_1: bool = true;
132}
133
134// Additional v5.0 packet implementations
135
136/// `PacketKind` implementation for v5.0 PINGREQ packet
137impl PacketKind for crate::mqtt::packet::v5_0::Pingreq {
138    const IS_PINGREQ: bool = true;
139    const IS_V5_0: bool = true;
140}
141
142impl PacketKind for crate::mqtt::packet::v5_0::Pingresp {
143    const IS_PINGRESP: bool = true;
144    const IS_V5_0: bool = true;
145}
146
147impl PacketKind for crate::mqtt::packet::v5_0::Disconnect {
148    const IS_DISCONNECT: bool = true;
149    const IS_V5_0: bool = true;
150}
151
152/// `PacketKind` implementation for v5.0 AUTH packet (v5.0 exclusive)
153impl PacketKind for crate::mqtt::packet::v5_0::Auth {
154    const IS_AUTH: bool = true;
155    const IS_V5_0: bool = true;
156}
157
158/// `PacketKind` implementation for references to packet types
159///
160/// This implementation forwards all flags from the referenced type,
161/// allowing packet references to be used with the same type checking.
162impl<T: PacketKind> PacketKind for &T {
163    const IS_CONNECT: bool = T::IS_CONNECT;
164    const IS_CONNACK: bool = T::IS_CONNACK;
165    const IS_PUBLISH: bool = T::IS_PUBLISH;
166    const IS_PUBACK: bool = T::IS_PUBACK;
167    const IS_PUBREC: bool = T::IS_PUBREC;
168    const IS_PUBREL: bool = T::IS_PUBREL;
169    const IS_PUBCOMP: bool = T::IS_PUBCOMP;
170    const IS_SUBSCRIBE: bool = T::IS_SUBSCRIBE;
171    const IS_SUBACK: bool = T::IS_SUBACK;
172    const IS_UNSUBSCRIBE: bool = T::IS_UNSUBSCRIBE;
173    const IS_UNSUBACK: bool = T::IS_UNSUBACK;
174    const IS_PINGREQ: bool = T::IS_PINGREQ;
175    const IS_PINGRESP: bool = T::IS_PINGRESP;
176    const IS_DISCONNECT: bool = T::IS_DISCONNECT;
177    const IS_AUTH: bool = T::IS_AUTH;
178    const IS_V3_1_1: bool = T::IS_V3_1_1;
179    const IS_V5_0: bool = T::IS_V5_0;
180}
181
182/// `PacketKind` implementation for `GenericPacket` enum
183///
184/// For enum types, all flags are `false` at compile time since the actual
185/// packet type is determined at runtime. This implementation provides a
186/// fallback for generic packet handling where compile-time type information
187/// is not available.
188impl<PacketIdType> PacketKind for crate::mqtt::packet::GenericPacket<PacketIdType>
189where
190    PacketIdType: crate::mqtt::packet::IsPacketId + serde::Serialize,
191{
192    // All flags use default (false) values
193}
194
195// Generic packet implementations for v3.1.1
196
197/// `PacketKind` implementation for generic v3.1.1 PUBLISH packet
198impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericPublish<PacketIdType>
199where
200    PacketIdType: crate::mqtt::packet::IsPacketId,
201    PacketIdType: 'static, // Ensure PacketIdType is not u16 implicitly
202{
203    const IS_PUBLISH: bool = true;
204    const IS_V3_1_1: bool = true;
205}
206
207impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericPuback<PacketIdType>
208where
209    PacketIdType: crate::mqtt::packet::IsPacketId,
210{
211    const IS_PUBACK: bool = true;
212    const IS_V3_1_1: bool = true;
213}
214
215impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericPubrec<PacketIdType>
216where
217    PacketIdType: crate::mqtt::packet::IsPacketId,
218{
219    const IS_PUBREC: bool = true;
220    const IS_V3_1_1: bool = true;
221}
222
223impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericPubrel<PacketIdType>
224where
225    PacketIdType: crate::mqtt::packet::IsPacketId,
226{
227    const IS_PUBREL: bool = true;
228    const IS_V3_1_1: bool = true;
229}
230
231impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericPubcomp<PacketIdType>
232where
233    PacketIdType: crate::mqtt::packet::IsPacketId,
234{
235    const IS_PUBCOMP: bool = true;
236    const IS_V3_1_1: bool = true;
237}
238
239impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericSubscribe<PacketIdType>
240where
241    PacketIdType: crate::mqtt::packet::IsPacketId,
242{
243    const IS_SUBSCRIBE: bool = true;
244    const IS_V3_1_1: bool = true;
245}
246
247impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericSuback<PacketIdType>
248where
249    PacketIdType: crate::mqtt::packet::IsPacketId,
250{
251    const IS_SUBACK: bool = true;
252    const IS_V3_1_1: bool = true;
253}
254
255impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericUnsubscribe<PacketIdType>
256where
257    PacketIdType: crate::mqtt::packet::IsPacketId,
258{
259    const IS_UNSUBSCRIBE: bool = true;
260    const IS_V3_1_1: bool = true;
261}
262
263impl<PacketIdType> PacketKind for crate::mqtt::packet::v3_1_1::GenericUnsuback<PacketIdType>
264where
265    PacketIdType: crate::mqtt::packet::IsPacketId,
266{
267    const IS_UNSUBACK: bool = true;
268    const IS_V3_1_1: bool = true;
269}
270
271// Generic packet implementations for v5.0
272impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericPublish<PacketIdType>
273where
274    PacketIdType: crate::mqtt::packet::IsPacketId,
275{
276    const IS_PUBLISH: bool = true;
277    const IS_V5_0: bool = true;
278}
279
280impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericPuback<PacketIdType>
281where
282    PacketIdType: crate::mqtt::packet::IsPacketId,
283{
284    const IS_PUBACK: bool = true;
285    const IS_V5_0: bool = true;
286}
287
288impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericPubrec<PacketIdType>
289where
290    PacketIdType: crate::mqtt::packet::IsPacketId,
291{
292    const IS_PUBREC: bool = true;
293    const IS_V5_0: bool = true;
294}
295
296impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericPubrel<PacketIdType>
297where
298    PacketIdType: crate::mqtt::packet::IsPacketId,
299{
300    const IS_PUBREL: bool = true;
301    const IS_V5_0: bool = true;
302}
303
304impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericPubcomp<PacketIdType>
305where
306    PacketIdType: crate::mqtt::packet::IsPacketId,
307{
308    const IS_PUBCOMP: bool = true;
309    const IS_V5_0: bool = true;
310}
311
312impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericSubscribe<PacketIdType>
313where
314    PacketIdType: crate::mqtt::packet::IsPacketId,
315{
316    const IS_SUBSCRIBE: bool = true;
317    const IS_V5_0: bool = true;
318}
319
320impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericSuback<PacketIdType>
321where
322    PacketIdType: crate::mqtt::packet::IsPacketId,
323{
324    const IS_SUBACK: bool = true;
325    const IS_V5_0: bool = true;
326}
327
328impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericUnsubscribe<PacketIdType>
329where
330    PacketIdType: crate::mqtt::packet::IsPacketId,
331{
332    const IS_UNSUBSCRIBE: bool = true;
333    const IS_V5_0: bool = true;
334}
335
336impl<PacketIdType> PacketKind for crate::mqtt::packet::v5_0::GenericUnsuback<PacketIdType>
337where
338    PacketIdType: crate::mqtt::packet::IsPacketId,
339{
340    const IS_UNSUBACK: bool = true;
341    const IS_V5_0: bool = true;
342}