mqtt_protocol_core/mqtt/packet/
kind.rs

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