mqtt_tiny/packets/
packet.rs

1//! A type-erased MQTT packet
2
3use crate::anyvec::AnyVec;
4use crate::err;
5use crate::error::{Data, DecoderError};
6use crate::packets::connack::Connack;
7use crate::packets::connect::Connect;
8use crate::packets::disconnect::Disconnect;
9use crate::packets::pingreq::Pingreq;
10use crate::packets::pingresp::Pingresp;
11use crate::packets::puback::Puback;
12use crate::packets::pubcomp::Pubcomp;
13use crate::packets::publish::Publish;
14use crate::packets::pubrec::Pubrec;
15use crate::packets::pubrel::Pubrel;
16use crate::packets::suback::Suback;
17use crate::packets::subscribe::Subscribe;
18use crate::packets::unsuback::Unsuback;
19use crate::packets::unsubscribe::Unsubscribe;
20use crate::packets::TryFromIterator;
21
22/// A type-erased MQTT packet
23#[derive(Debug, Clone, PartialEq, Eq)]
24pub enum Packet<TopicsSeq, TopicsQosSeq, Bytes> {
25    /// An [`Connack`] packet
26    Connack(Connack),
27    /// An [`Connect`] packet
28    Connect(Connect<Bytes>),
29    /// An [`Disconnect`] packet
30    Disconnect(Disconnect),
31    /// An [`Pingreq`] packet
32    Pingreq(Pingreq),
33    /// An [`Pingresp`] packet
34    Pingresp(Pingresp),
35    /// An [`Puback`] packet
36    Puback(Puback),
37    /// An [`Pubcomp`] packet
38    Pubcomp(Pubcomp),
39    /// An [`Publish`] packet
40    Publish(Publish<Bytes>),
41    /// An [`Pubrec`] packet
42    Pubrec(Pubrec),
43    /// An [`Pubrel`] packet
44    Pubrel(Pubrel),
45    /// An [`Suback`] packet
46    Suback(Suback),
47    /// An [`Subscribe`] packet
48    Subscribe(Subscribe<TopicsQosSeq, Bytes>),
49    /// An [`Unsuback`] packet
50    Unsuback(Unsuback),
51    /// An [`Unsubscribe`] packet
52    Unsubscribe(Unsubscribe<TopicsSeq, Bytes>),
53}
54impl<TopicsSeq, TopicsQosSeq, Bytes> TryFromIterator for Packet<TopicsSeq, TopicsQosSeq, Bytes>
55where
56    TopicsSeq: AnyVec<Bytes>,
57    TopicsQosSeq: AnyVec<(Bytes, u8)>,
58    Bytes: AnyVec<u8>,
59{
60    fn try_from_iter<T>(iter: T) -> Result<Self, DecoderError>
61    where
62        T: IntoIterator<Item = u8>,
63    {
64        // We have to peek at the header to determine the type
65        let mut decoder = iter.into_iter().peekable();
66        let header = decoder.peek().ok_or(err!(Data::Truncated, "empty packet"))?;
67
68        // Select the appropriate packet depending on the type
69        match header >> 4 {
70            Connack::TYPE => Connack::try_from_iter(&mut decoder).map(Self::Connack),
71            Connect::<Bytes>::TYPE => Connect::try_from_iter(&mut decoder).map(Self::Connect),
72            Disconnect::TYPE => Disconnect::try_from_iter(&mut decoder).map(Self::Disconnect),
73            Pingreq::TYPE => Pingreq::try_from_iter(&mut decoder).map(Self::Pingreq),
74            Pingresp::TYPE => Pingresp::try_from_iter(&mut decoder).map(Self::Pingresp),
75            Puback::TYPE => Puback::try_from_iter(&mut decoder).map(Self::Puback),
76            Pubcomp::TYPE => Pubcomp::try_from_iter(&mut decoder).map(Self::Pubcomp),
77            Publish::<Bytes>::TYPE => Publish::try_from_iter(&mut decoder).map(Self::Publish),
78            Pubrec::TYPE => Pubrec::try_from_iter(&mut decoder).map(Self::Pubrec),
79            Pubrel::TYPE => Pubrel::try_from_iter(&mut decoder).map(Self::Pubrel),
80            Suback::TYPE => Suback::try_from_iter(&mut decoder).map(Self::Suback),
81            Subscribe::<TopicsQosSeq, Bytes>::TYPE => Subscribe::try_from_iter(&mut decoder).map(Self::Subscribe),
82            Unsuback::TYPE => Unsuback::try_from_iter(&mut decoder).map(Self::Unsuback),
83            Unsubscribe::<TopicsSeq, Bytes>::TYPE => Unsubscribe::try_from_iter(&mut decoder).map(Self::Unsubscribe),
84            _ => Err(err!(Data::SpecViolation, "unknown packet type"))?,
85        }
86    }
87}
88impl<TopicsSeq, TopicsQosSeq, Bytes> IntoIterator for Packet<TopicsSeq, TopicsQosSeq, Bytes>
89where
90    TopicsSeq: AnyVec<Bytes>,
91    TopicsQosSeq: AnyVec<(Bytes, u8)>,
92    Bytes: AnyVec<u8>,
93{
94    type Item = u8;
95    type IntoIter = PacketIter<TopicsSeq, TopicsQosSeq, Bytes>;
96
97    fn into_iter(self) -> Self::IntoIter {
98        match self {
99            Self::Connack(this) => PacketIter::Connack(this.into_iter()),
100            Self::Connect(this) => PacketIter::Connect(this.into_iter()),
101            Self::Disconnect(this) => PacketIter::Disconnect(this.into_iter()),
102            Self::Pingreq(this) => PacketIter::Pingreq(this.into_iter()),
103            Self::Pingresp(this) => PacketIter::Pingresp(this.into_iter()),
104            Self::Puback(this) => PacketIter::Puback(this.into_iter()),
105            Self::Pubcomp(this) => PacketIter::Pubcomp(this.into_iter()),
106            Self::Publish(this) => PacketIter::Publish(this.into_iter()),
107            Self::Pubrec(this) => PacketIter::Pubreq(this.into_iter()),
108            Self::Pubrel(this) => PacketIter::Pubrel(this.into_iter()),
109            Self::Suback(this) => PacketIter::Suback(this.into_iter()),
110            Self::Subscribe(this) => PacketIter::Subscribe(this.into_iter()),
111            Self::Unsuback(this) => PacketIter::Unsuback(this.into_iter()),
112            Self::Unsubscribe(this) => PacketIter::Unsubscribe(this.into_iter()),
113        }
114    }
115}
116
117/// A packet-type-erased iterator over the encoded representation
118pub enum PacketIter<TopicsSeq, TopicsQosSeq, Bytes>
119where
120    TopicsSeq: AnyVec<Bytes>,
121    TopicsQosSeq: AnyVec<(Bytes, u8)>,
122    Bytes: AnyVec<u8>,
123{
124    /// An [`Connack`] packet iterator
125    Connack(<Connack as IntoIterator>::IntoIter),
126    /// An [`Connect`] packet iterator
127    Connect(<Connect<Bytes> as IntoIterator>::IntoIter),
128    /// An [`Disconnect`] packet iterator
129    Disconnect(<Disconnect as IntoIterator>::IntoIter),
130    /// An [`Pingreq`] packet iterator
131    Pingreq(<Pingreq as IntoIterator>::IntoIter),
132    /// An [`Pingresp`] packet iterator
133    Pingresp(<Pingresp as IntoIterator>::IntoIter),
134    /// An [`Puback`] packet iterator
135    Puback(<Puback as IntoIterator>::IntoIter),
136    /// An [`Pubcomp`] packet iterator
137    Pubcomp(<Pubcomp as IntoIterator>::IntoIter),
138    /// An [`Publish`] packet iterator
139    Publish(<Publish<Bytes> as IntoIterator>::IntoIter),
140    /// An [`Pubrec`] packet iterator
141    Pubreq(<Pubrec as IntoIterator>::IntoIter),
142    /// An [`Pubrel`] packet iterator
143    Pubrel(<Pubrel as IntoIterator>::IntoIter),
144    /// An [`Suback`] packet iterator
145    Suback(<Suback as IntoIterator>::IntoIter),
146    /// An [`Subscribe`] packet iterator
147    Subscribe(<Subscribe<TopicsQosSeq, Bytes> as IntoIterator>::IntoIter),
148    /// An [`Unsuback`] packet iterator
149    Unsuback(<Unsuback as IntoIterator>::IntoIter),
150    /// An [`Unsubscribe`] packet iterator
151    Unsubscribe(<Unsubscribe<TopicsSeq, Bytes> as IntoIterator>::IntoIter),
152}
153impl<TopicsSeq, TopicsQosSeq, Bytes> Iterator for PacketIter<TopicsSeq, TopicsQosSeq, Bytes>
154where
155    TopicsSeq: AnyVec<Bytes>,
156    TopicsQosSeq: AnyVec<(Bytes, u8)>,
157    Bytes: AnyVec<u8>,
158{
159    type Item = u8;
160
161    fn next(&mut self) -> Option<Self::Item> {
162        match self {
163            Self::Connack(iter) => iter.next(),
164            Self::Connect(iter) => iter.next(),
165            Self::Disconnect(iter) => iter.next(),
166            Self::Pingreq(iter) => iter.next(),
167            Self::Pingresp(iter) => iter.next(),
168            Self::Puback(iter) => iter.next(),
169            Self::Pubcomp(iter) => iter.next(),
170            Self::Publish(iter) => iter.next(),
171            Self::Pubreq(iter) => iter.next(),
172            Self::Pubrel(iter) => iter.next(),
173            Self::Suback(iter) => iter.next(),
174            Self::Subscribe(iter) => iter.next(),
175            Self::Unsuback(iter) => iter.next(),
176            Self::Unsubscribe(iter) => iter.next(),
177        }
178    }
179}