mqtt_tiny/packets/
_signal.rs

1/// Defines an ACK-like packet (i.e. a response packet with a single 16bit packet-ID field)
2#[rustfmt::skip]
3macro_rules! emptylike {
4    ($docstr:expr, $type:ident => $typeconst:expr) => {
5        #[doc = $docstr]
6        #[derive(Debug, Clone, PartialEq, Eq)]
7        pub struct $type {
8            _private: ()
9        }
10        impl $type {
11            /// The packet type constant
12            pub const TYPE: u8 = $typeconst;
13
14            /// For this packet, the body length is fixed
15            const BODY_LEN: usize = 0;
16
17            /// Creates a new packet
18            #[allow(clippy::new_without_default, reason = "packets should not be constructed via `Default`")]
19            pub const fn new() -> Self {
20                Self { _private: () }
21            }
22        }
23        impl $crate::packets::TryFromIterator for $type {
24            fn try_from_iter<T>(iter: T) -> Result<Self, crate::error::DecoderError>
25            where
26                T: IntoIterator<Item = u8>,
27            {
28                use crate::err;
29                use crate::coding::Decoder;
30                use crate::error::Data;
31
32                // Read packet:
33                //  - header type and `0` flags
34                //  - packet len
35                //  - packet I
36                let mut decoder = Decoder::new(iter);
37                let (Self::TYPE, _flags) = decoder.header()? else {
38                    return Err(err!(Data::SpecViolation, "invalid packet type"))?;
39                };
40                let Self::BODY_LEN = decoder.packetlen()? else {
41                    return Err(err!(Data::SpecViolation, "invalid packet length"))?;
42                };
43        
44                // Init self
45                Ok(Self { _private: () })
46            }
47        }
48        impl IntoIterator for $type {
49            type Item = u8;
50            #[rustfmt::skip]
51            type IntoIter = 
52                // Complex iterator built out of the individual message fields
53                core::iter::Chain<core::iter::Chain<
54                    // - header type and `0` flags
55                    $crate::coding::encoder::Unit, $crate::coding::encoder::U8Iter>, 
56                    // - packet len
57                    $crate::coding::encoder::PacketLenIter>;
58        
59            fn into_iter(self) -> Self::IntoIter {
60                use crate::coding::Encoder;
61
62                // Write packet:
63                //  - header type and `0` flags
64                //  - packet len
65                Encoder::default()
66                    .header(Self::TYPE, [false, false, false, false])
67                    .packetlen(Self::BODY_LEN)
68                    .into_iter()
69            }
70        }
71    };
72}
73
74pub mod disconnect {
75    //! MQTT [`DISCONNECT`](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718090)
76    emptylike! {
77        "An MQTT [`DISCONNECT` packet](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718090)",
78        Disconnect => 14
79    }
80}
81
82pub mod pingreq {
83    //! MQTT [`PINGREQ`](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718081)
84    emptylike! {
85        "An MQTT [`PINGREQ` packet](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718081)",
86        Pingreq => 12
87    }
88}
89
90pub mod pingresp {
91    //! MQTT [`PINGRESP`](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718086)
92    emptylike! {
93        "An MQTT [`PINGRESP` packet](https://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718086)",
94        Pingresp => 13
95    }
96}