1use nom::{
8 bits,
9 bytes::complete::take_while_m_n,
10 error::{Error, ErrorKind, FromExternalError},
11 sequence::tuple,
12 IResult, Parser,
13};
14use nom_supreme::ParserExt;
15
16use super::{
17 errors::MPacketHeaderError,
18 qos::{mquality_of_service, MQualityOfService},
19};
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub struct MPacketHeader {
23 pub kind: MPacketKind,
24 pub remaining_length: u32,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum MPacketKind {
29 Connect,
30 Connack,
31 Publish {
32 dup: bool,
33 qos: MQualityOfService,
34 retain: bool,
35 },
36 Puback,
37 Pubrec,
38 Pubrel,
39 Pubcomp,
40 Subscribe,
41 Suback,
42 Unsubscribe,
43 Unsuback,
44 Pingreq,
45 Pingresp,
46 Disconnect,
47}
48
49impl MPacketKind {
50 pub fn to_byte(&self) -> u8 {
51 match self {
52 MPacketKind::Connect => 1 << 4,
53 MPacketKind::Connack => 2 << 4,
54 MPacketKind::Publish { dup, qos, retain } => {
55 let upper = 0b0011;
56 let dup = if *dup { 0b1000 } else { 0 };
57 let retain = u8::from(*retain);
58 let qos = match qos {
59 MQualityOfService::AtMostOnce => 0b0000,
60 MQualityOfService::AtLeastOnce => 0b0001,
61 MQualityOfService::ExactlyOnce => 0b0010,
62 } << 1;
63
64 (upper << 4) | dup | retain | qos
65 }
66 MPacketKind::Puback => 4 << 4,
67 MPacketKind::Pubrec => 5 << 4,
68 MPacketKind::Pubrel => (6 << 4) | 2,
69 MPacketKind::Pubcomp => 7 << 4,
70 MPacketKind::Subscribe => (8 << 4) | 2,
71 MPacketKind::Suback => 9 << 4,
72 MPacketKind::Unsubscribe => (10 << 4) | 2,
73 MPacketKind::Unsuback => 11 << 4,
74 MPacketKind::Pingreq => 12 << 4,
75 MPacketKind::Pingresp => 13 << 4,
76 MPacketKind::Disconnect => 14 << 4,
77 }
78 }
79}
80
81fn mpacketkind(input: &[u8]) -> IResult<&[u8], MPacketKind> {
82 let (input, (upper, lower)): (_, (u8, u8)) =
83 bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((
84 nom::bits::complete::take(4usize),
85 nom::bits::complete::take(4usize),
86 )))(input)?;
87
88 let (input, kind) = match (upper, lower) {
89 (1, 0b0000) => (input, MPacketKind::Connect),
90 (2, 0b0000) => (input, MPacketKind::Connack),
91 (3, lower) => {
92 let dup = lower & 0b1000 != 0;
93 let retain = lower & 0b0001 != 0;
94 let qos = match mquality_of_service((lower & 0b0110) >> 1) {
95 Ok(qos) => qos,
96 Err(e) => {
97 return Err(nom::Err::Error(Error::from_external_error(
98 input,
99 ErrorKind::MapRes,
100 e,
101 )));
102 }
103 };
104 (input, MPacketKind::Publish { qos, dup, retain })
105 }
106 (4, 0b0000) => (input, MPacketKind::Puback),
107 (5, 0b0000) => (input, MPacketKind::Pubrec),
108 (6, 0b0010) => (input, MPacketKind::Pubrel),
109 (7, 0b0000) => (input, MPacketKind::Pubcomp),
110 (8, 0b0010) => (input, MPacketKind::Subscribe),
111 (9, 0b0000) => (input, MPacketKind::Suback),
112 (10, 0b0010) => (input, MPacketKind::Unsubscribe),
113 (11, 0b0000) => (input, MPacketKind::Unsuback),
114 (12, 0b0000) => (input, MPacketKind::Pingreq),
115 (13, 0b0000) => (input, MPacketKind::Pingresp),
116 (14, 0b0000) => (input, MPacketKind::Disconnect),
117 (inv_type, _) => {
118 return Err(nom::Err::Error(Error::from_external_error(
119 input,
120 ErrorKind::MapRes,
121 MPacketHeaderError::InvalidPacketType(inv_type),
122 )))
123 }
124 };
125
126 Ok((input, kind))
127}
128
129pub fn decode_variable_length(bytes: &[u8]) -> u32 {
130 let mut output: u32 = 0;
131
132 for (exp, val) in bytes.iter().enumerate() {
133 output += (*val as u32 & 0b0111_1111) * 128u32.pow(exp as u32);
134 }
135
136 output
137}
138
139pub fn mfixedheader(input: &[u8]) -> IResult<&[u8], MPacketHeader> {
140 let (input, kind) = mpacketkind(input)?;
141 let (input, remaining_length) = nom::number::complete::u8
142 .and(take_while_m_n(0, 3, |b| b & 0b1000_0000 != 0))
143 .recognize()
144 .map(decode_variable_length)
145 .parse(input)?;
146
147 Ok((
148 input,
149 MPacketHeader {
150 kind,
151 remaining_length,
152 },
153 ))
154}
155
156#[cfg(test)]
157mod tests {
158 use crate::v3::{
159 header::{MPacketHeader, MPacketKind},
160 qos::MQualityOfService,
161 };
162
163 use super::{decode_variable_length, mfixedheader, mpacketkind};
164
165 #[test]
166 fn check_variable_length_decoding() {
167 let input = &[64];
168
169 let output = decode_variable_length(input);
170 assert_eq!(output, 64);
171
172 let input = &[193, 2];
173
174 let output = decode_variable_length(input);
175 assert_eq!(output, 321);
176 }
177
178 #[test]
179 fn check_header_publish_flags() {
180 let input = &[0b0011_1101, 0];
181
182 let (input, header) = mfixedheader(input).unwrap();
183
184 assert_eq!(input, &[]);
185
186 assert_eq!(
187 header,
188 MPacketHeader {
189 remaining_length: 0,
190 kind: MPacketKind::Publish {
191 dup: true,
192 qos: MQualityOfService::ExactlyOnce,
193 retain: true
194 }
195 }
196 );
197 }
198
199 #[test]
200 fn check_invalid_header_publish_flags() {
201 let input = &[0b0011_1111, 0];
202
203 mfixedheader(input).unwrap_err();
204 }
205
206 #[test]
207 fn check_roundtrip_packet_kind() {
208 fn test(mp: MPacketKind) {
209 assert_eq!(mp, mpacketkind(&[mp.to_byte()]).unwrap().1);
210 }
211
212 test(MPacketKind::Connect);
213 test(MPacketKind::Connack);
214 test(MPacketKind::Publish {
215 dup: false,
216 qos: MQualityOfService::AtMostOnce,
217 retain: false,
218 });
219 test(MPacketKind::Publish {
220 dup: false,
221 qos: MQualityOfService::AtLeastOnce,
222 retain: false,
223 });
224 test(MPacketKind::Publish {
225 dup: false,
226 qos: MQualityOfService::ExactlyOnce,
227 retain: false,
228 });
229 test(MPacketKind::Publish {
230 dup: true,
231 qos: MQualityOfService::AtMostOnce,
232 retain: false,
233 });
234 test(MPacketKind::Publish {
235 dup: false,
236 qos: MQualityOfService::AtMostOnce,
237 retain: true,
238 });
239 test(MPacketKind::Puback);
240 test(MPacketKind::Pubrec);
241 test(MPacketKind::Pubrel);
242 test(MPacketKind::Pubcomp);
243 test(MPacketKind::Subscribe);
244 test(MPacketKind::Suback);
245 test(MPacketKind::Unsubscribe);
246 test(MPacketKind::Unsuback);
247 test(MPacketKind::Pingreq);
248 test(MPacketKind::Pingresp);
249 test(MPacketKind::Disconnect);
250 }
251}