mqtt_protocol_core/mqtt/connection/
sendable.rs

1use crate::mqtt::connection::role;
2use crate::mqtt::connection::role::RoleType;
3use crate::mqtt::connection::sendable_role::SendableRole;
4use crate::mqtt::connection::sendable_version::SendableVersion;
5/**
6 * MIT License
7 *
8 * Copyright (c) 2025 Takatoshi Kondo
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in all
18 * copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28use crate::mqtt::connection::GenericConnection;
29use crate::mqtt::connection::GenericEvent;
30use crate::mqtt::packet::kind::PacketKind;
31use crate::mqtt::packet::GenericPacket;
32use crate::mqtt::packet::IsPacketId;
33use crate::mqtt::result_code::MqttError;
34use alloc::vec::Vec;
35use core::fmt::Debug;
36use tracing::trace;
37
38/// Core trait for sendable packets
39pub trait Sendable<Role, PacketIdType>: PacketKind
40where
41    Role: RoleType,
42    PacketIdType: IsPacketId,
43{
44    fn dispatch_send(
45        self,
46        connection: &mut GenericConnection<Role, PacketIdType>,
47    ) -> Vec<GenericEvent<PacketIdType>>;
48}
49
50/// Trait for connection send behavior
51pub trait SendBehavior<Role, PacketIdType>
52where
53    Role: RoleType,
54    PacketIdType: IsPacketId,
55{
56    fn send<T>(&mut self, packet: T) -> Vec<GenericEvent<PacketIdType>>
57    where
58        T: Sendable<Role, PacketIdType>;
59}
60
61/// Helper trait for type-specific send operations
62pub trait SendableHelper<Role, PacketIdType>: PacketKind + Sized
63where
64    Role: RoleType,
65    PacketIdType: IsPacketId,
66{
67    // v3.1.1 methods
68    fn send_connect_v3_1_1(
69        self,
70        _connection: &mut GenericConnection<Role, PacketIdType>,
71    ) -> Vec<GenericEvent<PacketIdType>> {
72        unreachable!("send_connect_v3_1_1 not implemented for this type")
73    }
74
75    fn send_connack_v3_1_1(
76        self,
77        _connection: &mut GenericConnection<Role, PacketIdType>,
78    ) -> Vec<GenericEvent<PacketIdType>> {
79        unreachable!("send_connack_v3_1_1 not implemented for this type")
80    }
81
82    fn send_publish_v3_1_1(
83        self,
84        _connection: &mut GenericConnection<Role, PacketIdType>,
85    ) -> Vec<GenericEvent<PacketIdType>> {
86        unreachable!("send_publish_v3_1_1 not implemented for this type")
87    }
88
89    fn send_puback_v3_1_1(
90        self,
91        _connection: &mut GenericConnection<Role, PacketIdType>,
92    ) -> Vec<GenericEvent<PacketIdType>> {
93        unreachable!("send_puback_v3_1_1 not implemented for this type")
94    }
95
96    fn send_pubrec_v3_1_1(
97        self,
98        _connection: &mut GenericConnection<Role, PacketIdType>,
99    ) -> Vec<GenericEvent<PacketIdType>> {
100        unreachable!("send_pubrec_v3_1_1 not implemented for this type")
101    }
102
103    fn send_pubrel_v3_1_1(
104        self,
105        _connection: &mut GenericConnection<Role, PacketIdType>,
106    ) -> Vec<GenericEvent<PacketIdType>> {
107        unreachable!("send_pubrel_v3_1_1 not implemented for this type")
108    }
109
110    fn send_pubcomp_v3_1_1(
111        self,
112        _connection: &mut GenericConnection<Role, PacketIdType>,
113    ) -> Vec<GenericEvent<PacketIdType>> {
114        unreachable!("send_pubcomp_v3_1_1 not implemented for this type")
115    }
116
117    fn send_subscribe_v3_1_1(
118        self,
119        _connection: &mut GenericConnection<Role, PacketIdType>,
120    ) -> Vec<GenericEvent<PacketIdType>> {
121        unreachable!("send_subscribe_v3_1_1 not implemented for this type")
122    }
123
124    fn send_suback_v3_1_1(
125        self,
126        _connection: &mut GenericConnection<Role, PacketIdType>,
127    ) -> Vec<GenericEvent<PacketIdType>> {
128        unreachable!("send_suback_v3_1_1 not implemented for this type")
129    }
130
131    fn send_unsubscribe_v3_1_1(
132        self,
133        _connection: &mut GenericConnection<Role, PacketIdType>,
134    ) -> Vec<GenericEvent<PacketIdType>> {
135        unreachable!("send_unsubscribe_v3_1_1 not implemented for this type")
136    }
137
138    fn send_unsuback_v3_1_1(
139        self,
140        _connection: &mut GenericConnection<Role, PacketIdType>,
141    ) -> Vec<GenericEvent<PacketIdType>> {
142        unreachable!("send_unsuback_v3_1_1 not implemented for this type")
143    }
144
145    fn send_pingreq_v3_1_1(
146        self,
147        _connection: &mut GenericConnection<Role, PacketIdType>,
148    ) -> Vec<GenericEvent<PacketIdType>> {
149        unreachable!("send_pingreq_v3_1_1 not implemented for this type")
150    }
151
152    fn send_pingresp_v3_1_1(
153        self,
154        _connection: &mut GenericConnection<Role, PacketIdType>,
155    ) -> Vec<GenericEvent<PacketIdType>> {
156        unreachable!("send_pingresp_v3_1_1 not implemented for this type")
157    }
158
159    fn send_disconnect_v3_1_1(
160        self,
161        _connection: &mut GenericConnection<Role, PacketIdType>,
162    ) -> Vec<GenericEvent<PacketIdType>> {
163        unreachable!("send_disconnect_v3_1_1 not implemented for this type")
164    }
165
166    // v5.0 methods
167    fn send_connect_v5_0(
168        self,
169        _connection: &mut GenericConnection<Role, PacketIdType>,
170    ) -> Vec<GenericEvent<PacketIdType>> {
171        unreachable!("send_connect_v5_0 not implemented for this type")
172    }
173
174    fn send_connack_v5_0(
175        self,
176        _connection: &mut GenericConnection<Role, PacketIdType>,
177    ) -> Vec<GenericEvent<PacketIdType>> {
178        unreachable!("send_connack_v5_0 not implemented for this type")
179    }
180
181    fn send_publish_v5_0(
182        self,
183        _connection: &mut GenericConnection<Role, PacketIdType>,
184    ) -> Vec<GenericEvent<PacketIdType>> {
185        unreachable!("send_publish_v5_0 not implemented for this type")
186    }
187
188    fn send_puback_v5_0(
189        self,
190        _connection: &mut GenericConnection<Role, PacketIdType>,
191    ) -> Vec<GenericEvent<PacketIdType>> {
192        unreachable!("send_puback_v5_0 not implemented for this type")
193    }
194
195    fn send_pubrec_v5_0(
196        self,
197        _connection: &mut GenericConnection<Role, PacketIdType>,
198    ) -> Vec<GenericEvent<PacketIdType>> {
199        unreachable!("send_pubrec_v5_0 not implemented for this type")
200    }
201
202    fn send_pubrel_v5_0(
203        self,
204        _connection: &mut GenericConnection<Role, PacketIdType>,
205    ) -> Vec<GenericEvent<PacketIdType>> {
206        unreachable!("send_pubrel_v5_0 not implemented for this type")
207    }
208
209    fn send_pubcomp_v5_0(
210        self,
211        _connection: &mut GenericConnection<Role, PacketIdType>,
212    ) -> Vec<GenericEvent<PacketIdType>> {
213        unreachable!("send_pubcomp_v5_0 not implemented for this type")
214    }
215
216    fn send_subscribe_v5_0(
217        self,
218        _connection: &mut GenericConnection<Role, PacketIdType>,
219    ) -> Vec<GenericEvent<PacketIdType>> {
220        unreachable!("send_subscribe_v5_0 not implemented for this type")
221    }
222
223    fn send_suback_v5_0(
224        self,
225        _connection: &mut GenericConnection<Role, PacketIdType>,
226    ) -> Vec<GenericEvent<PacketIdType>> {
227        unreachable!("send_suback_v5_0 not implemented for this type")
228    }
229
230    fn send_unsubscribe_v5_0(
231        self,
232        _connection: &mut GenericConnection<Role, PacketIdType>,
233    ) -> Vec<GenericEvent<PacketIdType>> {
234        unreachable!("send_unsubscribe_v5_0 not implemented for this type")
235    }
236
237    fn send_unsuback_v5_0(
238        self,
239        _connection: &mut GenericConnection<Role, PacketIdType>,
240    ) -> Vec<GenericEvent<PacketIdType>> {
241        unreachable!("send_unsuback_v5_0 not implemented for this type")
242    }
243
244    fn send_pingreq_v5_0(
245        self,
246        _connection: &mut GenericConnection<Role, PacketIdType>,
247    ) -> Vec<GenericEvent<PacketIdType>> {
248        unreachable!("send_pingreq_v5_0 not implemented for this type")
249    }
250
251    fn send_pingresp_v5_0(
252        self,
253        _connection: &mut GenericConnection<Role, PacketIdType>,
254    ) -> Vec<GenericEvent<PacketIdType>> {
255        unreachable!("send_pingresp_v5_0 not implemented for this type")
256    }
257
258    fn send_disconnect_v5_0(
259        self,
260        _connection: &mut GenericConnection<Role, PacketIdType>,
261    ) -> Vec<GenericEvent<PacketIdType>> {
262        unreachable!("send_disconnect_v5_0 not implemented for this type")
263    }
264
265    fn send_auth_v5_0(
266        self,
267        _connection: &mut GenericConnection<Role, PacketIdType>,
268    ) -> Vec<GenericEvent<PacketIdType>> {
269        unreachable!("send_auth_v5_0 not implemented for this type")
270    }
271}
272
273// Generic implementation for specific packet types with compile-time dispatch
274impl<Role, PacketIdType, T> Sendable<Role, PacketIdType> for T
275where
276    Role: role::RoleType,
277    PacketIdType: IsPacketId,
278    T: SendableRole<Role>
279        + SendableVersion
280        + core::fmt::Display
281        + Debug
282        + PacketKind
283        + SendableHelper<Role, PacketIdType>,
284{
285    fn dispatch_send(
286        self,
287        connection: &mut GenericConnection<Role, PacketIdType>,
288    ) -> Vec<GenericEvent<PacketIdType>> {
289        // Version check first
290        if !T::check(&connection.get_protocol_version()) {
291            return vec![GenericEvent::NotifyError(MqttError::VersionMismatch)];
292        }
293
294        trace!("Static dispatch sent: {}", self);
295        // Compile-time dispatch based on packet type and version
296        // The compiler will eliminate unused branches for specific types
297        if T::IS_CONNECT {
298            if T::IS_V3_1_1 {
299                self.send_connect_v3_1_1(connection)
300            } else if T::IS_V5_0 {
301                self.send_connect_v5_0(connection)
302            } else {
303                unreachable!("Invalid version for CONNECT packet")
304            }
305        } else if T::IS_CONNACK {
306            if T::IS_V3_1_1 {
307                self.send_connack_v3_1_1(connection)
308            } else if T::IS_V5_0 {
309                self.send_connack_v5_0(connection)
310            } else {
311                unreachable!("Invalid version for CONNACK packet")
312            }
313        } else if T::IS_PUBLISH {
314            if T::IS_V3_1_1 {
315                self.send_publish_v3_1_1(connection)
316            } else if T::IS_V5_0 {
317                self.send_publish_v5_0(connection)
318            } else {
319                unreachable!("Invalid version for PUBLISH packet")
320            }
321        } else if T::IS_PUBACK {
322            if T::IS_V3_1_1 {
323                self.send_puback_v3_1_1(connection)
324            } else if T::IS_V5_0 {
325                self.send_puback_v5_0(connection)
326            } else {
327                unreachable!("Invalid version for PUBACK packet")
328            }
329        } else if T::IS_PUBREC {
330            if T::IS_V3_1_1 {
331                self.send_pubrec_v3_1_1(connection)
332            } else if T::IS_V5_0 {
333                self.send_pubrec_v5_0(connection)
334            } else {
335                unreachable!("Invalid version for PUBREC packet")
336            }
337        } else if T::IS_PUBREL {
338            if T::IS_V3_1_1 {
339                self.send_pubrel_v3_1_1(connection)
340            } else if T::IS_V5_0 {
341                self.send_pubrel_v5_0(connection)
342            } else {
343                unreachable!("Invalid version for PUBREL packet")
344            }
345        } else if T::IS_PUBCOMP {
346            if T::IS_V3_1_1 {
347                self.send_pubcomp_v3_1_1(connection)
348            } else if T::IS_V5_0 {
349                self.send_pubcomp_v5_0(connection)
350            } else {
351                unreachable!("Invalid version for PUBCOMP packet")
352            }
353        } else if T::IS_SUBSCRIBE {
354            if T::IS_V3_1_1 {
355                self.send_subscribe_v3_1_1(connection)
356            } else if T::IS_V5_0 {
357                self.send_subscribe_v5_0(connection)
358            } else {
359                unreachable!("Invalid version for SUBSCRIBE packet")
360            }
361        } else if T::IS_SUBACK {
362            if T::IS_V3_1_1 {
363                self.send_suback_v3_1_1(connection)
364            } else if T::IS_V5_0 {
365                self.send_suback_v5_0(connection)
366            } else {
367                unreachable!("Invalid version for SUBACK packet")
368            }
369        } else if T::IS_UNSUBSCRIBE {
370            if T::IS_V3_1_1 {
371                self.send_unsubscribe_v3_1_1(connection)
372            } else if T::IS_V5_0 {
373                self.send_unsubscribe_v5_0(connection)
374            } else {
375                unreachable!("Invalid version for UNSUBSCRIBE packet")
376            }
377        } else if T::IS_UNSUBACK {
378            if T::IS_V3_1_1 {
379                self.send_unsuback_v3_1_1(connection)
380            } else if T::IS_V5_0 {
381                self.send_unsuback_v5_0(connection)
382            } else {
383                unreachable!("Invalid version for UNSUBACK packet")
384            }
385        } else if T::IS_PINGREQ {
386            if T::IS_V3_1_1 {
387                self.send_pingreq_v3_1_1(connection)
388            } else if T::IS_V5_0 {
389                self.send_pingreq_v5_0(connection)
390            } else {
391                unreachable!("Invalid version for PINGREQ packet")
392            }
393        } else if T::IS_PINGRESP {
394            if T::IS_V3_1_1 {
395                self.send_pingresp_v3_1_1(connection)
396            } else if T::IS_V5_0 {
397                self.send_pingresp_v5_0(connection)
398            } else {
399                unreachable!("Invalid version for PINGRESP packet")
400            }
401        } else if T::IS_DISCONNECT {
402            if T::IS_V3_1_1 {
403                self.send_disconnect_v3_1_1(connection)
404            } else if T::IS_V5_0 {
405                self.send_disconnect_v5_0(connection)
406            } else {
407                unreachable!("Invalid version for DISCONNECT packet")
408            }
409        } else if T::IS_AUTH {
410            if T::IS_V5_0 {
411                self.send_auth_v5_0(connection)
412            } else {
413                unreachable!("AUTH packet is only valid for v5.0")
414            }
415        } else {
416            unreachable!("Unknown packet type")
417        }
418    }
419}
420
421// Sendable implementation for GenericPacket (runtime dispatch)
422impl<PacketIdType> Sendable<role::Client, PacketIdType> for GenericPacket<PacketIdType>
423where
424    PacketIdType: IsPacketId,
425{
426    fn dispatch_send(
427        self,
428        connection: &mut GenericConnection<role::Client, PacketIdType>,
429    ) -> Vec<GenericEvent<PacketIdType>> {
430        connection.send(self)
431    }
432}
433
434impl<PacketIdType> Sendable<role::Server, PacketIdType> for GenericPacket<PacketIdType>
435where
436    PacketIdType: IsPacketId,
437{
438    fn dispatch_send(
439        self,
440        connection: &mut GenericConnection<role::Server, PacketIdType>,
441    ) -> Vec<GenericEvent<PacketIdType>> {
442        connection.send(self)
443    }
444}
445
446impl<PacketIdType> Sendable<role::Any, PacketIdType> for GenericPacket<PacketIdType>
447where
448    PacketIdType: IsPacketId,
449{
450    fn dispatch_send(
451        self,
452        connection: &mut GenericConnection<role::Any, PacketIdType>,
453    ) -> Vec<GenericEvent<PacketIdType>> {
454        connection.send(self)
455    }
456}