mqtt_protocol_core/mqtt/packet/
as_concrete.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 */
24use crate::mqtt::packet::enum_packet::Packet;
25use crate::mqtt::packet::v3_1_1;
26use crate::mqtt::packet::v5_0;
27
28/// Trait to extract a reference to a concrete type from an enum Packet, if applicable.
29pub trait AsConcrete<T> {
30    fn as_concrete(&self) -> Option<&T>;
31}
32
33/// Trait to extract an owned concrete type from an enum Packet by consuming it, if applicable.
34pub trait IntoConcreteOwned<T> {
35    fn into_concrete_owned(self) -> Option<T>;
36}
37
38// Identity implementation: concrete type is already T
39impl<T> AsConcrete<T> for T {
40    fn as_concrete(&self) -> Option<&T> {
41        Some(self)
42    }
43}
44
45// Identity implementation for owned version: concrete type is already T
46impl<T> IntoConcreteOwned<T> for T {
47    fn into_concrete_owned(self) -> Option<T> {
48        Some(self)
49    }
50}
51
52// v3.1.1 packets
53impl AsConcrete<v3_1_1::Connect> for Packet {
54    fn as_concrete(&self) -> Option<&v3_1_1::Connect> {
55        match self {
56            Packet::V3_1_1Connect(v) => Some(v),
57            _ => None,
58        }
59    }
60}
61
62impl AsConcrete<v3_1_1::Connack> for Packet {
63    fn as_concrete(&self) -> Option<&v3_1_1::Connack> {
64        match self {
65            Packet::V3_1_1Connack(v) => Some(v),
66            _ => None,
67        }
68    }
69}
70
71impl AsConcrete<v3_1_1::Subscribe> for Packet {
72    fn as_concrete(&self) -> Option<&v3_1_1::Subscribe> {
73        match self {
74            Packet::V3_1_1Subscribe(v) => Some(v),
75            _ => None,
76        }
77    }
78}
79
80impl AsConcrete<v3_1_1::Suback> for Packet {
81    fn as_concrete(&self) -> Option<&v3_1_1::Suback> {
82        match self {
83            Packet::V3_1_1Suback(v) => Some(v),
84            _ => None,
85        }
86    }
87}
88
89impl AsConcrete<v3_1_1::Unsubscribe> for Packet {
90    fn as_concrete(&self) -> Option<&v3_1_1::Unsubscribe> {
91        match self {
92            Packet::V3_1_1Unsubscribe(v) => Some(v),
93            _ => None,
94        }
95    }
96}
97
98impl AsConcrete<v3_1_1::Unsuback> for Packet {
99    fn as_concrete(&self) -> Option<&v3_1_1::Unsuback> {
100        match self {
101            Packet::V3_1_1Unsuback(v) => Some(v),
102            _ => None,
103        }
104    }
105}
106
107impl AsConcrete<v3_1_1::Publish> for Packet {
108    fn as_concrete(&self) -> Option<&v3_1_1::Publish> {
109        match self {
110            Packet::V3_1_1Publish(v) => Some(v),
111            _ => None,
112        }
113    }
114}
115
116impl AsConcrete<v3_1_1::Puback> for Packet {
117    fn as_concrete(&self) -> Option<&v3_1_1::Puback> {
118        match self {
119            Packet::V3_1_1Puback(v) => Some(v),
120            _ => None,
121        }
122    }
123}
124
125impl AsConcrete<v3_1_1::Pubrec> for Packet {
126    fn as_concrete(&self) -> Option<&v3_1_1::Pubrec> {
127        match self {
128            Packet::V3_1_1Pubrec(v) => Some(v),
129            _ => None,
130        }
131    }
132}
133
134impl AsConcrete<v3_1_1::Pubrel> for Packet {
135    fn as_concrete(&self) -> Option<&v3_1_1::Pubrel> {
136        match self {
137            Packet::V3_1_1Pubrel(v) => Some(v),
138            _ => None,
139        }
140    }
141}
142
143impl AsConcrete<v3_1_1::Pubcomp> for Packet {
144    fn as_concrete(&self) -> Option<&v3_1_1::Pubcomp> {
145        match self {
146            Packet::V3_1_1Pubcomp(v) => Some(v),
147            _ => None,
148        }
149    }
150}
151
152impl AsConcrete<v3_1_1::Disconnect> for Packet {
153    fn as_concrete(&self) -> Option<&v3_1_1::Disconnect> {
154        match self {
155            Packet::V3_1_1Disconnect(v) => Some(v),
156            _ => None,
157        }
158    }
159}
160
161impl AsConcrete<v3_1_1::Pingreq> for Packet {
162    fn as_concrete(&self) -> Option<&v3_1_1::Pingreq> {
163        match self {
164            Packet::V3_1_1Pingreq(v) => Some(v),
165            _ => None,
166        }
167    }
168}
169
170impl AsConcrete<v3_1_1::Pingresp> for Packet {
171    fn as_concrete(&self) -> Option<&v3_1_1::Pingresp> {
172        match self {
173            Packet::V3_1_1Pingresp(v) => Some(v),
174            _ => None,
175        }
176    }
177}
178
179// v5.0 packets
180impl AsConcrete<v5_0::Connect> for Packet {
181    fn as_concrete(&self) -> Option<&v5_0::Connect> {
182        match self {
183            Packet::V5_0Connect(v) => Some(v),
184            _ => None,
185        }
186    }
187}
188
189impl AsConcrete<v5_0::Connack> for Packet {
190    fn as_concrete(&self) -> Option<&v5_0::Connack> {
191        match self {
192            Packet::V5_0Connack(v) => Some(v),
193            _ => None,
194        }
195    }
196}
197
198impl AsConcrete<v5_0::Subscribe> for Packet {
199    fn as_concrete(&self) -> Option<&v5_0::Subscribe> {
200        match self {
201            Packet::V5_0Subscribe(v) => Some(v),
202            _ => None,
203        }
204    }
205}
206
207impl AsConcrete<v5_0::Suback> for Packet {
208    fn as_concrete(&self) -> Option<&v5_0::Suback> {
209        match self {
210            Packet::V5_0Suback(v) => Some(v),
211            _ => None,
212        }
213    }
214}
215
216impl AsConcrete<v5_0::Unsubscribe> for Packet {
217    fn as_concrete(&self) -> Option<&v5_0::Unsubscribe> {
218        match self {
219            Packet::V5_0Unsubscribe(v) => Some(v),
220            _ => None,
221        }
222    }
223}
224
225impl AsConcrete<v5_0::Unsuback> for Packet {
226    fn as_concrete(&self) -> Option<&v5_0::Unsuback> {
227        match self {
228            Packet::V5_0Unsuback(v) => Some(v),
229            _ => None,
230        }
231    }
232}
233
234impl AsConcrete<v5_0::Publish> for Packet {
235    fn as_concrete(&self) -> Option<&v5_0::Publish> {
236        match self {
237            Packet::V5_0Publish(v) => Some(v),
238            _ => None,
239        }
240    }
241}
242
243impl AsConcrete<v5_0::Puback> for Packet {
244    fn as_concrete(&self) -> Option<&v5_0::Puback> {
245        match self {
246            Packet::V5_0Puback(v) => Some(v),
247            _ => None,
248        }
249    }
250}
251
252impl AsConcrete<v5_0::Pubrec> for Packet {
253    fn as_concrete(&self) -> Option<&v5_0::Pubrec> {
254        match self {
255            Packet::V5_0Pubrec(v) => Some(v),
256            _ => None,
257        }
258    }
259}
260
261impl AsConcrete<v5_0::Pubrel> for Packet {
262    fn as_concrete(&self) -> Option<&v5_0::Pubrel> {
263        match self {
264            Packet::V5_0Pubrel(v) => Some(v),
265            _ => None,
266        }
267    }
268}
269
270impl AsConcrete<v5_0::Pubcomp> for Packet {
271    fn as_concrete(&self) -> Option<&v5_0::Pubcomp> {
272        match self {
273            Packet::V5_0Pubcomp(v) => Some(v),
274            _ => None,
275        }
276    }
277}
278
279impl AsConcrete<v5_0::Disconnect> for Packet {
280    fn as_concrete(&self) -> Option<&v5_0::Disconnect> {
281        match self {
282            Packet::V5_0Disconnect(v) => Some(v),
283            _ => None,
284        }
285    }
286}
287
288impl AsConcrete<v5_0::Pingreq> for Packet {
289    fn as_concrete(&self) -> Option<&v5_0::Pingreq> {
290        match self {
291            Packet::V5_0Pingreq(v) => Some(v),
292            _ => None,
293        }
294    }
295}
296
297impl AsConcrete<v5_0::Pingresp> for Packet {
298    fn as_concrete(&self) -> Option<&v5_0::Pingresp> {
299        match self {
300            Packet::V5_0Pingresp(v) => Some(v),
301            _ => None,
302        }
303    }
304}
305
306impl AsConcrete<v5_0::Auth> for Packet {
307    fn as_concrete(&self) -> Option<&v5_0::Auth> {
308        match self {
309            Packet::V5_0Auth(v) => Some(v),
310            _ => None,
311        }
312    }
313}
314
315// v3.1.1 packets - move versions
316impl IntoConcreteOwned<v3_1_1::Connect> for Packet {
317    fn into_concrete_owned(self) -> Option<v3_1_1::Connect> {
318        match self {
319            Packet::V3_1_1Connect(v) => Some(v),
320            _ => None,
321        }
322    }
323}
324
325impl IntoConcreteOwned<v3_1_1::Connack> for Packet {
326    fn into_concrete_owned(self) -> Option<v3_1_1::Connack> {
327        match self {
328            Packet::V3_1_1Connack(v) => Some(v),
329            _ => None,
330        }
331    }
332}
333
334impl IntoConcreteOwned<v3_1_1::Subscribe> for Packet {
335    fn into_concrete_owned(self) -> Option<v3_1_1::Subscribe> {
336        match self {
337            Packet::V3_1_1Subscribe(v) => Some(v),
338            _ => None,
339        }
340    }
341}
342
343impl IntoConcreteOwned<v3_1_1::Suback> for Packet {
344    fn into_concrete_owned(self) -> Option<v3_1_1::Suback> {
345        match self {
346            Packet::V3_1_1Suback(v) => Some(v),
347            _ => None,
348        }
349    }
350}
351
352impl IntoConcreteOwned<v3_1_1::Unsubscribe> for Packet {
353    fn into_concrete_owned(self) -> Option<v3_1_1::Unsubscribe> {
354        match self {
355            Packet::V3_1_1Unsubscribe(v) => Some(v),
356            _ => None,
357        }
358    }
359}
360
361impl IntoConcreteOwned<v3_1_1::Unsuback> for Packet {
362    fn into_concrete_owned(self) -> Option<v3_1_1::Unsuback> {
363        match self {
364            Packet::V3_1_1Unsuback(v) => Some(v),
365            _ => None,
366        }
367    }
368}
369
370impl IntoConcreteOwned<v3_1_1::Publish> for Packet {
371    fn into_concrete_owned(self) -> Option<v3_1_1::Publish> {
372        match self {
373            Packet::V3_1_1Publish(v) => Some(v),
374            _ => None,
375        }
376    }
377}
378
379impl IntoConcreteOwned<v3_1_1::Puback> for Packet {
380    fn into_concrete_owned(self) -> Option<v3_1_1::Puback> {
381        match self {
382            Packet::V3_1_1Puback(v) => Some(v),
383            _ => None,
384        }
385    }
386}
387
388impl IntoConcreteOwned<v3_1_1::Pubrec> for Packet {
389    fn into_concrete_owned(self) -> Option<v3_1_1::Pubrec> {
390        match self {
391            Packet::V3_1_1Pubrec(v) => Some(v),
392            _ => None,
393        }
394    }
395}
396
397impl IntoConcreteOwned<v3_1_1::Pubrel> for Packet {
398    fn into_concrete_owned(self) -> Option<v3_1_1::Pubrel> {
399        match self {
400            Packet::V3_1_1Pubrel(v) => Some(v),
401            _ => None,
402        }
403    }
404}
405
406impl IntoConcreteOwned<v3_1_1::Pubcomp> for Packet {
407    fn into_concrete_owned(self) -> Option<v3_1_1::Pubcomp> {
408        match self {
409            Packet::V3_1_1Pubcomp(v) => Some(v),
410            _ => None,
411        }
412    }
413}
414
415impl IntoConcreteOwned<v3_1_1::Disconnect> for Packet {
416    fn into_concrete_owned(self) -> Option<v3_1_1::Disconnect> {
417        match self {
418            Packet::V3_1_1Disconnect(v) => Some(v),
419            _ => None,
420        }
421    }
422}
423
424impl IntoConcreteOwned<v3_1_1::Pingreq> for Packet {
425    fn into_concrete_owned(self) -> Option<v3_1_1::Pingreq> {
426        match self {
427            Packet::V3_1_1Pingreq(v) => Some(v),
428            _ => None,
429        }
430    }
431}
432
433impl IntoConcreteOwned<v3_1_1::Pingresp> for Packet {
434    fn into_concrete_owned(self) -> Option<v3_1_1::Pingresp> {
435        match self {
436            Packet::V3_1_1Pingresp(v) => Some(v),
437            _ => None,
438        }
439    }
440}
441
442// v5.0 packets - move versions
443impl IntoConcreteOwned<v5_0::Connect> for Packet {
444    fn into_concrete_owned(self) -> Option<v5_0::Connect> {
445        match self {
446            Packet::V5_0Connect(v) => Some(v),
447            _ => None,
448        }
449    }
450}
451
452impl IntoConcreteOwned<v5_0::Connack> for Packet {
453    fn into_concrete_owned(self) -> Option<v5_0::Connack> {
454        match self {
455            Packet::V5_0Connack(v) => Some(v),
456            _ => None,
457        }
458    }
459}
460
461impl IntoConcreteOwned<v5_0::Subscribe> for Packet {
462    fn into_concrete_owned(self) -> Option<v5_0::Subscribe> {
463        match self {
464            Packet::V5_0Subscribe(v) => Some(v),
465            _ => None,
466        }
467    }
468}
469
470impl IntoConcreteOwned<v5_0::Suback> for Packet {
471    fn into_concrete_owned(self) -> Option<v5_0::Suback> {
472        match self {
473            Packet::V5_0Suback(v) => Some(v),
474            _ => None,
475        }
476    }
477}
478
479impl IntoConcreteOwned<v5_0::Unsubscribe> for Packet {
480    fn into_concrete_owned(self) -> Option<v5_0::Unsubscribe> {
481        match self {
482            Packet::V5_0Unsubscribe(v) => Some(v),
483            _ => None,
484        }
485    }
486}
487
488impl IntoConcreteOwned<v5_0::Unsuback> for Packet {
489    fn into_concrete_owned(self) -> Option<v5_0::Unsuback> {
490        match self {
491            Packet::V5_0Unsuback(v) => Some(v),
492            _ => None,
493        }
494    }
495}
496
497impl IntoConcreteOwned<v5_0::Publish> for Packet {
498    fn into_concrete_owned(self) -> Option<v5_0::Publish> {
499        match self {
500            Packet::V5_0Publish(v) => Some(v),
501            _ => None,
502        }
503    }
504}
505
506impl IntoConcreteOwned<v5_0::Puback> for Packet {
507    fn into_concrete_owned(self) -> Option<v5_0::Puback> {
508        match self {
509            Packet::V5_0Puback(v) => Some(v),
510            _ => None,
511        }
512    }
513}
514
515impl IntoConcreteOwned<v5_0::Pubrec> for Packet {
516    fn into_concrete_owned(self) -> Option<v5_0::Pubrec> {
517        match self {
518            Packet::V5_0Pubrec(v) => Some(v),
519            _ => None,
520        }
521    }
522}
523
524impl IntoConcreteOwned<v5_0::Pubrel> for Packet {
525    fn into_concrete_owned(self) -> Option<v5_0::Pubrel> {
526        match self {
527            Packet::V5_0Pubrel(v) => Some(v),
528            _ => None,
529        }
530    }
531}
532
533impl IntoConcreteOwned<v5_0::Pubcomp> for Packet {
534    fn into_concrete_owned(self) -> Option<v5_0::Pubcomp> {
535        match self {
536            Packet::V5_0Pubcomp(v) => Some(v),
537            _ => None,
538        }
539    }
540}
541
542impl IntoConcreteOwned<v5_0::Disconnect> for Packet {
543    fn into_concrete_owned(self) -> Option<v5_0::Disconnect> {
544        match self {
545            Packet::V5_0Disconnect(v) => Some(v),
546            _ => None,
547        }
548    }
549}
550
551impl IntoConcreteOwned<v5_0::Pingreq> for Packet {
552    fn into_concrete_owned(self) -> Option<v5_0::Pingreq> {
553        match self {
554            Packet::V5_0Pingreq(v) => Some(v),
555            _ => None,
556        }
557    }
558}
559
560impl IntoConcreteOwned<v5_0::Pingresp> for Packet {
561    fn into_concrete_owned(self) -> Option<v5_0::Pingresp> {
562        match self {
563            Packet::V5_0Pingresp(v) => Some(v),
564            _ => None,
565        }
566    }
567}
568
569impl IntoConcreteOwned<v5_0::Auth> for Packet {
570    fn into_concrete_owned(self) -> Option<v5_0::Auth> {
571        match self {
572            Packet::V5_0Auth(v) => Some(v),
573            _ => None,
574        }
575    }
576}