use crate::*;
mod connack;
mod connect;
mod disconnect;
mod ping;
mod puback;
mod pubcomp;
mod publish;
mod pubrec;
mod pubrel;
mod suback;
mod subscribe;
mod unsuback;
mod unsubscribe;
pub use connack::*;
pub use connect::*;
pub use disconnect::*;
pub use ping::*;
pub use puback::*;
pub use pubcomp::*;
pub use publish::*;
pub use pubrec::*;
pub use pubrel::*;
pub use suback::*;
pub use subscribe::*;
pub use unsuback::*;
pub use unsubscribe::*;
#[derive(Debug, Clone, PartialEq)]
pub enum Packet {
Connect(Connect),
ConnAck(ConnAck),
Publish(Publish),
PubAck(PubAck),
PubRec(PubRec),
PubRel(PubRel),
PubComp(PubComp),
Subscribe(Subscribe),
SubAck(SubAck),
Unsubscribe(Unsubscribe),
UnsubAck(UnsubAck),
PingReq,
PingResp,
Disconnect,
}
#[repr(u8)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum PropertyType {
PayloadFormatIndicator = 1,
MessageExpiryInterval = 2,
ContentType = 3,
ResponseTopic = 8,
CorrelationData = 9,
SubscriptionIdentifier = 11,
SessionExpiryInterval = 17,
AssignedClientIdentifier = 18,
ServerKeepAlive = 19,
AuthenticationMethod = 21,
AuthenticationData = 22,
RequestProblemInformation = 23,
WillDelayInterval = 24,
RequestResponseInformation = 25,
ResponseInformation = 26,
ServerReference = 28,
ReasonString = 31,
ReceiveMaximum = 33,
TopicAliasMaximum = 34,
TopicAlias = 35,
MaximumQos = 36,
RetainAvailable = 37,
UserProperty = 38,
MaximumPacketSize = 39,
WildcardSubscriptionAvailable = 40,
SubscriptionIdentifierAvailable = 41,
SharedSubscriptionAvailable = 42,
}
fn property(num: u8) -> Result<PropertyType, Error> {
let property = match num {
1 => PropertyType::PayloadFormatIndicator,
2 => PropertyType::MessageExpiryInterval,
3 => PropertyType::ContentType,
8 => PropertyType::ResponseTopic,
9 => PropertyType::CorrelationData,
11 => PropertyType::SubscriptionIdentifier,
17 => PropertyType::SessionExpiryInterval,
18 => PropertyType::AssignedClientIdentifier,
19 => PropertyType::ServerKeepAlive,
21 => PropertyType::AuthenticationMethod,
22 => PropertyType::AuthenticationData,
23 => PropertyType::RequestProblemInformation,
24 => PropertyType::WillDelayInterval,
25 => PropertyType::RequestResponseInformation,
26 => PropertyType::ResponseInformation,
28 => PropertyType::ServerReference,
31 => PropertyType::ReasonString,
33 => PropertyType::ReceiveMaximum,
34 => PropertyType::TopicAliasMaximum,
35 => PropertyType::TopicAlias,
36 => PropertyType::MaximumQos,
37 => PropertyType::RetainAvailable,
38 => PropertyType::UserProperty,
39 => PropertyType::MaximumPacketSize,
40 => PropertyType::WildcardSubscriptionAvailable,
41 => PropertyType::SubscriptionIdentifierAvailable,
42 => PropertyType::SharedSubscriptionAvailable,
num => return Err(Error::InvalidPropertyType(num)),
};
Ok(property)
}
pub fn read(stream: &mut BytesMut, max_size: usize) -> Result<Packet, Error> {
let fixed_header = check(stream.iter(), max_size)?;
let packet = stream.split_to(fixed_header.frame_length());
let packet_type = fixed_header.packet_type()?;
if fixed_header.remaining_len == 0 {
return match packet_type {
PacketType::PingReq => Ok(Packet::PingReq),
PacketType::PingResp => Ok(Packet::PingResp),
PacketType::Disconnect => Ok(Packet::Disconnect),
_ => Err(Error::PayloadRequired),
};
}
let packet = packet.freeze();
let packet = match packet_type {
PacketType::Connect => Packet::Connect(Connect::read(fixed_header, packet)?),
PacketType::ConnAck => Packet::ConnAck(ConnAck::read(fixed_header, packet)?),
PacketType::Publish => Packet::Publish(Publish::read(fixed_header, packet)?),
PacketType::PubAck => Packet::PubAck(PubAck::read(fixed_header, packet)?),
PacketType::PubRec => Packet::PubRec(PubRec::read(fixed_header, packet)?),
PacketType::PubRel => Packet::PubRel(PubRel::read(fixed_header, packet)?),
PacketType::PubComp => Packet::PubComp(PubComp::read(fixed_header, packet)?),
PacketType::Subscribe => Packet::Subscribe(Subscribe::read(fixed_header, packet)?),
PacketType::SubAck => Packet::SubAck(SubAck::read(fixed_header, packet)?),
PacketType::Unsubscribe => Packet::Unsubscribe(Unsubscribe::read(fixed_header, packet)?),
PacketType::UnsubAck => Packet::UnsubAck(UnsubAck::read(fixed_header, packet)?),
PacketType::PingReq => Packet::PingReq,
PacketType::PingResp => Packet::PingResp,
PacketType::Disconnect => Packet::Disconnect,
};
Ok(packet)
}