use bytes::Bytes;
use bytestring::ByteString;
use std::num::NonZeroU16;
use super::proto::{Protocol, QoS};
#[repr(u8)]
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
pub enum ConnectCode {
ConnectionAccepted = 0,
UnacceptableProtocolVersion = 1,
IdentifierRejected = 2,
ServiceUnavailable = 3,
BadUserNameOrPassword = 4,
NotAuthorized = 5,
Reserved = 6,
}
const_enum!(ConnectCode: u8);
impl ConnectCode {
pub fn reason(self) -> &'static str {
match self {
ConnectCode::ConnectionAccepted => "Connection Accepted",
ConnectCode::UnacceptableProtocolVersion => {
"Connection Refused, unacceptable protocol version"
}
ConnectCode::IdentifierRejected => "Connection Refused, identifier rejected",
ConnectCode::ServiceUnavailable => "Connection Refused, Server unavailable",
ConnectCode::BadUserNameOrPassword => {
"Connection Refused, bad user name or password"
}
ConnectCode::NotAuthorized => "Connection Refused, not authorized",
_ => "Connection Refused",
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct LastWill {
pub qos: QoS,
pub retain: bool,
pub topic: ByteString,
pub message: Bytes,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Connect {
pub protocol: Protocol,
pub clean_session: bool,
pub keep_alive: u16,
pub last_will: Option<LastWill>,
pub client_id: ByteString,
pub username: Option<ByteString>,
pub password: Option<Bytes>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct Publish {
pub dup: bool,
pub retain: bool,
pub qos: QoS,
pub topic: ByteString,
pub packet_id: Option<NonZeroU16>,
pub payload: Bytes,
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SubscribeReturnCode {
Success(QoS),
Failure,
}
#[derive(Debug, PartialEq, Clone)]
pub enum Packet {
Connect(Connect),
ConnectAck {
session_present: bool,
return_code: ConnectCode,
},
Publish(Publish),
PublishAck {
packet_id: NonZeroU16,
},
PublishReceived {
packet_id: NonZeroU16,
},
PublishRelease {
packet_id: NonZeroU16,
},
PublishComplete {
packet_id: NonZeroU16,
},
Subscribe {
packet_id: NonZeroU16,
topic_filters: Vec<(ByteString, QoS)>,
},
SubscribeAck {
packet_id: NonZeroU16,
status: Vec<SubscribeReturnCode>,
},
Unsubscribe {
packet_id: NonZeroU16,
topic_filters: Vec<ByteString>,
},
UnsubscribeAck {
packet_id: NonZeroU16,
},
PingRequest,
PingResponse,
Disconnect,
}
impl Packet {
#[inline]
pub fn packet_type(&self) -> u8 {
match *self {
Packet::Connect { .. } => CONNECT,
Packet::ConnectAck { .. } => CONNACK,
Packet::Publish { .. } => PUBLISH,
Packet::PublishAck { .. } => PUBACK,
Packet::PublishReceived { .. } => PUBREC,
Packet::PublishRelease { .. } => PUBREL,
Packet::PublishComplete { .. } => PUBCOMP,
Packet::Subscribe { .. } => SUBSCRIBE,
Packet::SubscribeAck { .. } => SUBACK,
Packet::Unsubscribe { .. } => UNSUBSCRIBE,
Packet::UnsubscribeAck { .. } => UNSUBACK,
Packet::PingRequest => PINGREQ,
Packet::PingResponse => PINGRESP,
Packet::Disconnect => DISCONNECT,
}
}
pub fn packet_flags(&self) -> u8 {
match *self {
Packet::Publish(Publish {
dup, qos, retain, ..
}) => {
let mut b = qos as u8;
b <<= 1;
if dup {
b |= 0b1000;
}
if retain {
b |= 0b0001;
}
b
}
Packet::PublishRelease { .. }
| Packet::Subscribe { .. }
| Packet::Unsubscribe { .. } => 0b0010,
_ => 0,
}
}
}
impl From<Connect> for Packet {
fn from(val: Connect) -> Packet {
Packet::Connect(val)
}
}
impl From<Publish> for Packet {
fn from(val: Publish) -> Packet {
Packet::Publish(val)
}
}
pub const CONNECT: u8 = 1;
pub const CONNACK: u8 = 2;
pub const PUBLISH: u8 = 3;
pub const PUBACK: u8 = 4;
pub const PUBREC: u8 = 5;
pub const PUBREL: u8 = 6;
pub const PUBCOMP: u8 = 7;
pub const SUBSCRIBE: u8 = 8;
pub const SUBACK: u8 = 9;
pub const UNSUBSCRIBE: u8 = 10;
pub const UNSUBACK: u8 = 11;
pub const PINGREQ: u8 = 12;
pub const PINGRESP: u8 = 13;
pub const DISCONNECT: u8 = 14;