use crate::mqtt::packet::enum_packet::{GenericPacket, GenericPacketDisplay, GenericPacketTrait};
use crate::mqtt::packet::qos::Qos;
use crate::mqtt::packet::v3_1_1;
use crate::mqtt::packet::v5_0;
use crate::mqtt::packet::IsPacketId;
use crate::mqtt::packet::PacketType;
use crate::mqtt::result_code::MqttError;
use alloc::vec::Vec;
use serde::Serialize;
#[cfg(feature = "std")]
use std::io::IoSlice;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ResponsePacket {
V3_1_1Puback,
V3_1_1Pubrec,
V3_1_1Pubcomp,
V5_0Puback,
V5_0Pubrec,
V5_0Pubcomp,
}
#[derive(Serialize, Clone, PartialEq, Eq)]
pub enum GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
V3_1_1Publish(v3_1_1::GenericPublish<PacketIdType>),
V3_1_1Pubrel(v3_1_1::GenericPubrel<PacketIdType>),
V5_0Publish(v5_0::GenericPublish<PacketIdType>),
V5_0Pubrel(v5_0::GenericPubrel<PacketIdType>),
}
pub type StorePacket = GenericStorePacket<u16>;
impl<PacketIdType> core::fmt::Debug for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.fmt_debug(f)
}
}
impl<PacketIdType> core::fmt::Display for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.fmt_display(f)
}
}
impl<PacketIdType> GenericPacketTrait for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
fn size(&self) -> usize {
match self {
GenericStorePacket::V3_1_1Publish(p) => p.size(),
GenericStorePacket::V3_1_1Pubrel(p) => p.size(),
GenericStorePacket::V5_0Publish(p) => p.size(),
GenericStorePacket::V5_0Pubrel(p) => p.size(),
}
}
fn to_continuous_buffer(&self) -> Vec<u8> {
match self {
GenericStorePacket::V3_1_1Publish(p) => p.to_continuous_buffer(),
GenericStorePacket::V3_1_1Pubrel(p) => p.to_continuous_buffer(),
GenericStorePacket::V5_0Publish(p) => p.to_continuous_buffer(),
GenericStorePacket::V5_0Pubrel(p) => p.to_continuous_buffer(),
}
}
#[cfg(feature = "std")]
fn to_buffers(&self) -> Vec<IoSlice<'_>> {
match self {
GenericStorePacket::V3_1_1Publish(p) => p.to_buffers(),
GenericStorePacket::V3_1_1Pubrel(p) => p.to_buffers(),
GenericStorePacket::V5_0Publish(p) => p.to_buffers(),
GenericStorePacket::V5_0Pubrel(p) => p.to_buffers(),
}
}
}
impl<PacketIdType> GenericPacketDisplay for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
fn fmt_debug(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
GenericStorePacket::V3_1_1Publish(p) => p.fmt_debug(f),
GenericStorePacket::V3_1_1Pubrel(p) => p.fmt_debug(f),
GenericStorePacket::V5_0Publish(p) => p.fmt_debug(f),
GenericStorePacket::V5_0Pubrel(p) => p.fmt_debug(f),
}
}
fn fmt_display(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
GenericStorePacket::V3_1_1Publish(p) => p.fmt_display(f),
GenericStorePacket::V3_1_1Pubrel(p) => p.fmt_display(f),
GenericStorePacket::V5_0Publish(p) => p.fmt_display(f),
GenericStorePacket::V5_0Pubrel(p) => p.fmt_display(f),
}
}
}
impl<PacketIdType> GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
pub fn packet_type(&self) -> PacketType {
match self {
GenericStorePacket::V3_1_1Publish(_) => PacketType::Publish,
GenericStorePacket::V3_1_1Pubrel(_) => PacketType::Pubrel,
GenericStorePacket::V5_0Publish(_) => PacketType::Publish,
GenericStorePacket::V5_0Pubrel(_) => PacketType::Pubrel,
}
}
pub fn packet_id(&self) -> PacketIdType {
match self {
GenericStorePacket::V3_1_1Publish(p) => p.packet_id().unwrap(),
GenericStorePacket::V3_1_1Pubrel(p) => p.packet_id(),
GenericStorePacket::V5_0Publish(p) => p.packet_id().unwrap(),
GenericStorePacket::V5_0Pubrel(p) => p.packet_id(),
}
}
pub fn response_packet(&self) -> ResponsePacket {
match self {
GenericStorePacket::V3_1_1Publish(p) => match p.qos() {
Qos::AtLeastOnce => ResponsePacket::V3_1_1Puback,
Qos::ExactlyOnce => ResponsePacket::V3_1_1Pubrec,
_ => panic!("QoS 0 packets should not be stored"),
},
GenericStorePacket::V3_1_1Pubrel(_) => ResponsePacket::V3_1_1Pubcomp,
GenericStorePacket::V5_0Publish(p) => match p.qos() {
Qos::AtLeastOnce => ResponsePacket::V5_0Puback,
Qos::ExactlyOnce => ResponsePacket::V5_0Pubrec,
_ => panic!("QoS 0 packets should not be stored"),
},
GenericStorePacket::V5_0Pubrel(_) => ResponsePacket::V5_0Pubcomp,
}
}
}
impl<PacketIdType> TryFrom<v3_1_1::GenericPublish<PacketIdType>>
for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
type Error = MqttError;
fn try_from(publish: v3_1_1::GenericPublish<PacketIdType>) -> Result<Self, Self::Error> {
match publish.qos() {
Qos::AtMostOnce => Err(MqttError::InvalidQos),
_ => Ok(GenericStorePacket::V3_1_1Publish(publish)),
}
}
}
impl<PacketIdType> TryFrom<v5_0::GenericPublish<PacketIdType>> for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
type Error = MqttError;
fn try_from(publish: v5_0::GenericPublish<PacketIdType>) -> Result<Self, Self::Error> {
match publish.qos() {
Qos::AtMostOnce => Err(MqttError::InvalidQos),
_ => Ok(GenericStorePacket::V5_0Publish(publish)),
}
}
}
impl<PacketIdType> TryFrom<v3_1_1::GenericPubrel<PacketIdType>> for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
type Error = MqttError;
fn try_from(pubrel: v3_1_1::GenericPubrel<PacketIdType>) -> Result<Self, Self::Error> {
Ok(GenericStorePacket::V3_1_1Pubrel(pubrel))
}
}
impl<PacketIdType> TryFrom<v5_0::GenericPubrel<PacketIdType>> for GenericStorePacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
type Error = MqttError;
fn try_from(pubrel: v5_0::GenericPubrel<PacketIdType>) -> Result<Self, Self::Error> {
Ok(GenericStorePacket::V5_0Pubrel(pubrel))
}
}
impl<PacketIdType> From<GenericStorePacket<PacketIdType>> for GenericPacket<PacketIdType>
where
PacketIdType: IsPacketId + Serialize,
{
fn from(store_packet: GenericStorePacket<PacketIdType>) -> Self {
match store_packet {
GenericStorePacket::V3_1_1Publish(p) => GenericPacket::V3_1_1Publish(p),
GenericStorePacket::V3_1_1Pubrel(p) => GenericPacket::V3_1_1Pubrel(p),
GenericStorePacket::V5_0Publish(p) => GenericPacket::V5_0Publish(p),
GenericStorePacket::V5_0Pubrel(p) => GenericPacket::V5_0Pubrel(p),
}
}
}