embedded_mqtt/variable_header/
mod.rs

1use core::result::Result;
2
3use crate::{
4    status::Status,
5    fixed_header::{PacketType, PacketFlags},
6    error::{DecodeError, EncodeError},
7    codec::Encodable,
8};
9
10pub mod connect;
11pub mod connack;
12pub mod packet_identifier;
13pub mod publish;
14
15#[derive(Debug)]
16pub enum VariableHeader<'a> {
17    Connect(connect::Connect<'a>),
18    Connack(connack::Connack),
19    Subscribe(packet_identifier::PacketIdentifier),
20    Suback(packet_identifier::PacketIdentifier),
21    Publish(publish::Publish<'a>),
22    Puback(packet_identifier::PacketIdentifier),
23}
24
25pub trait HeaderDecode<'a>
26    where Self: core::marker::Sized {
27    fn decode(flags: PacketFlags, bytes: &'a [u8]) -> Result<Status<(usize, Self)>, DecodeError>;
28}
29
30pub type PacketId = u16;
31
32macro_rules! decode {
33    ($($name:ident, $parser:path;)+) => (
34        pub fn decode(r#type: PacketType, flags: PacketFlags, bytes: &'a [u8]) -> Option<Result<Status<(usize, Self)>, DecodeError>> {
35            Some(match r#type {
36                $(
37                    PacketType::$name => $parser(flags, bytes).map(|s| {
38                        match s {
39                            Status::Complete((offset, var_header)) => {
40                                Status::Complete((offset, VariableHeader::$name(var_header)))
41                            },
42                            Status::Partial(n) => Status::Partial(n),
43                        }
44                    }),
45                )+
46                _ => return None,
47            })
48        }
49    )
50}
51
52impl<'a> VariableHeader<'a> {
53    decode!(
54        Connect,   connect::Connect::decode;
55        Connack,   connack::Connack::decode;
56        Subscribe, packet_identifier::PacketIdentifier::decode;
57        Suback,    packet_identifier::PacketIdentifier::decode;
58        Publish,   publish::Publish::decode;
59        Puback,    packet_identifier::PacketIdentifier::decode;
60    );
61}
62
63macro_rules! encode {
64    ($($enum:ident;)+) => (
65        fn encoded_len(&self) -> usize {
66            match self {
67                $( &VariableHeader::$enum(ref c) => c.encoded_len(), )+
68            }
69        }
70
71        fn encode(&self, bytes: &mut [u8]) -> Result<usize, EncodeError> {
72            match self {
73                $( &VariableHeader::$enum(ref c) => c.encode(bytes), )+
74            }
75        }
76    )
77}
78
79impl<'buf> Encodable for VariableHeader<'buf> {
80    encode!(
81        Connect;
82        Connack;
83        Subscribe;
84        Suback;
85        Publish;
86        Puback;
87    );
88}