use std::fmt;
use std::num::NonZeroU16;
use bytes::Bytes;
use bytestring::ByteString;
use serde::{Deserialize, Serialize};
use crate::v5::PublishProperties;
pub(crate) const MQTT: &[u8] = b"MQTT";
pub(crate) const MQISDP: &[u8] = b"MQIsdp";
pub const MQTT_LEVEL_31: u8 = 3;
pub const MQTT_LEVEL_311: u8 = 4;
pub const MQTT_LEVEL_5: u8 = 5;
pub(crate) const WILL_QOS_SHIFT: u8 = 3;
pub(crate) const MAX_PACKET_SIZE: u32 = 0xF_FF_FF_FF;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
pub struct Protocol(pub u8);
impl Protocol {
#[inline]
pub fn name(self) -> &'static str {
match self {
Protocol(MQTT_LEVEL_311) => "MQTT",
Protocol(MQTT_LEVEL_31) => "MQIsdp",
Protocol(MQTT_LEVEL_5) => "MQTT",
Protocol(_) => "MQTT",
}
}
#[inline]
pub fn level(self) -> u8 {
self.0
}
}
impl Default for Protocol {
fn default() -> Self {
Protocol(MQTT_LEVEL_311)
}
}
prim_enum! {
#[derive(serde::Serialize, serde::Deserialize, PartialOrd, Ord, Hash)]
pub enum QoS {
AtMostOnce = 0,
AtLeastOnce = 1,
ExactlyOnce = 2
}
}
impl QoS {
#[inline]
pub fn value(&self) -> u8 {
match self {
QoS::AtMostOnce => 0,
QoS::AtLeastOnce => 1,
QoS::ExactlyOnce => 2,
}
}
#[inline]
pub fn less_value(&self, qos: QoS) -> QoS {
if self.value() < qos.value() {
*self
} else {
qos
}
}
}
impl From<QoS> for u8 {
fn from(v: QoS) -> Self {
v.value()
}
}
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ConnectFlags: u8 {
const USERNAME = 0b1000_0000;
const PASSWORD = 0b0100_0000;
const WILL_RETAIN = 0b0010_0000;
const WILL_QOS = 0b0001_1000;
const WILL = 0b0000_0100;
const CLEAN_START = 0b0000_0010;
}
}
bitflags::bitflags! {
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ConnectAckFlags: u8 {
const SESSION_PRESENT = 0b0000_0001;
}
}
pub(super) mod packet_type {
pub(crate) const CONNECT: u8 = 0b0001_0000;
pub(crate) const CONNACK: u8 = 0b0010_0000;
pub(crate) const PUBLISH_START: u8 = 0b0011_0000;
pub(crate) const PUBLISH_END: u8 = 0b0011_1111;
pub(crate) const PUBACK: u8 = 0b0100_0000;
pub(crate) const PUBREC: u8 = 0b0101_0000;
pub(crate) const PUBREL: u8 = 0b0110_0010;
pub(crate) const PUBCOMP: u8 = 0b0111_0000;
pub(crate) const SUBSCRIBE: u8 = 0b1000_0010;
pub(crate) const SUBACK: u8 = 0b1001_0000;
pub(crate) const UNSUBSCRIBE: u8 = 0b1010_0010;
pub(crate) const UNSUBACK: u8 = 0b1011_0000;
pub(crate) const PINGREQ: u8 = 0b1100_0000;
pub(crate) const PINGRESP: u8 = 0b1101_0000;
pub(crate) const DISCONNECT: u8 = 0b1110_0000;
pub(crate) const AUTH: u8 = 0b1111_0000;
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub(crate) struct FixedHeader {
pub(crate) first_byte: u8,
pub(crate) remaining_length: u32,
}
#[derive(Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct Publish {
pub dup: bool,
pub retain: bool,
pub qos: QoS,
pub topic: ByteString,
pub packet_id: Option<NonZeroU16>,
pub payload: Bytes,
pub properties: Option<PublishProperties>,
}
impl fmt::Debug for Publish {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Publish")
.field("packet_id", &self.packet_id)
.field("topic", &self.topic)
.field("dup", &self.dup)
.field("retain", &self.retain)
.field("qos", &self.qos)
.field("payload", &"<REDACTED>")
.field("properties", &self.properties)
.finish()
}
}