use crate::anyvec::AnyVec;
use crate::err;
use crate::error::{Data, DecoderError};
use crate::packets::connack::Connack;
use crate::packets::connect::Connect;
use crate::packets::disconnect::Disconnect;
use crate::packets::pingreq::Pingreq;
use crate::packets::pingresp::Pingresp;
use crate::packets::puback::Puback;
use crate::packets::pubcomp::Pubcomp;
use crate::packets::publish::Publish;
use crate::packets::pubrec::Pubrec;
use crate::packets::pubrel::Pubrel;
use crate::packets::suback::Suback;
use crate::packets::subscribe::Subscribe;
use crate::packets::unsuback::Unsuback;
use crate::packets::unsubscribe::Unsubscribe;
use crate::packets::TryFromIterator;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Packet<TopicsSeq, TopicsQosSeq, Bytes> {
Connack(Connack),
Connect(Connect<Bytes>),
Disconnect(Disconnect),
Pingreq(Pingreq),
Pingresp(Pingresp),
Puback(Puback),
Pubcomp(Pubcomp),
Publish(Publish<Bytes>),
Pubrec(Pubrec),
Pubrel(Pubrel),
Suback(Suback),
Subscribe(Subscribe<TopicsQosSeq, Bytes>),
Unsuback(Unsuback),
Unsubscribe(Unsubscribe<TopicsSeq, Bytes>),
}
impl<TopicsSeq, TopicsQosSeq, Bytes> TryFromIterator for Packet<TopicsSeq, TopicsQosSeq, Bytes>
where
TopicsSeq: AnyVec<Bytes>,
TopicsQosSeq: AnyVec<(Bytes, u8)>,
Bytes: AnyVec<u8>,
{
fn try_from_iter<T>(iter: T) -> Result<Self, DecoderError>
where
T: IntoIterator<Item = u8>,
{
let mut decoder = iter.into_iter().peekable();
let header = decoder.peek().ok_or(err!(Data::Truncated, "empty packet"))?;
match header >> 4 {
Connack::TYPE => Connack::try_from_iter(&mut decoder).map(Self::Connack),
Connect::<Bytes>::TYPE => Connect::try_from_iter(&mut decoder).map(Self::Connect),
Disconnect::TYPE => Disconnect::try_from_iter(&mut decoder).map(Self::Disconnect),
Pingreq::TYPE => Pingreq::try_from_iter(&mut decoder).map(Self::Pingreq),
Pingresp::TYPE => Pingresp::try_from_iter(&mut decoder).map(Self::Pingresp),
Puback::TYPE => Puback::try_from_iter(&mut decoder).map(Self::Puback),
Pubcomp::TYPE => Pubcomp::try_from_iter(&mut decoder).map(Self::Pubcomp),
Publish::<Bytes>::TYPE => Publish::try_from_iter(&mut decoder).map(Self::Publish),
Pubrec::TYPE => Pubrec::try_from_iter(&mut decoder).map(Self::Pubrec),
Pubrel::TYPE => Pubrel::try_from_iter(&mut decoder).map(Self::Pubrel),
Suback::TYPE => Suback::try_from_iter(&mut decoder).map(Self::Suback),
Subscribe::<TopicsQosSeq, Bytes>::TYPE => Subscribe::try_from_iter(&mut decoder).map(Self::Subscribe),
Unsuback::TYPE => Unsuback::try_from_iter(&mut decoder).map(Self::Unsuback),
Unsubscribe::<TopicsSeq, Bytes>::TYPE => Unsubscribe::try_from_iter(&mut decoder).map(Self::Unsubscribe),
_ => Err(err!(Data::SpecViolation, "unknown packet type"))?,
}
}
}
impl<TopicsSeq, TopicsQosSeq, Bytes> IntoIterator for Packet<TopicsSeq, TopicsQosSeq, Bytes>
where
TopicsSeq: AnyVec<Bytes>,
TopicsQosSeq: AnyVec<(Bytes, u8)>,
Bytes: AnyVec<u8>,
{
type Item = u8;
type IntoIter = PacketIter<TopicsSeq, TopicsQosSeq, Bytes>;
fn into_iter(self) -> Self::IntoIter {
match self {
Self::Connack(this) => PacketIter::Connack(this.into_iter()),
Self::Connect(this) => PacketIter::Connect(this.into_iter()),
Self::Disconnect(this) => PacketIter::Disconnect(this.into_iter()),
Self::Pingreq(this) => PacketIter::Pingreq(this.into_iter()),
Self::Pingresp(this) => PacketIter::Pingresp(this.into_iter()),
Self::Puback(this) => PacketIter::Puback(this.into_iter()),
Self::Pubcomp(this) => PacketIter::Pubcomp(this.into_iter()),
Self::Publish(this) => PacketIter::Publish(this.into_iter()),
Self::Pubrec(this) => PacketIter::Pubreq(this.into_iter()),
Self::Pubrel(this) => PacketIter::Pubrel(this.into_iter()),
Self::Suback(this) => PacketIter::Suback(this.into_iter()),
Self::Subscribe(this) => PacketIter::Subscribe(this.into_iter()),
Self::Unsuback(this) => PacketIter::Unsuback(this.into_iter()),
Self::Unsubscribe(this) => PacketIter::Unsubscribe(this.into_iter()),
}
}
}
pub enum PacketIter<TopicsSeq, TopicsQosSeq, Bytes>
where
TopicsSeq: AnyVec<Bytes>,
TopicsQosSeq: AnyVec<(Bytes, u8)>,
Bytes: AnyVec<u8>,
{
Connack(<Connack as IntoIterator>::IntoIter),
Connect(<Connect<Bytes> as IntoIterator>::IntoIter),
Disconnect(<Disconnect as IntoIterator>::IntoIter),
Pingreq(<Pingreq as IntoIterator>::IntoIter),
Pingresp(<Pingresp as IntoIterator>::IntoIter),
Puback(<Puback as IntoIterator>::IntoIter),
Pubcomp(<Pubcomp as IntoIterator>::IntoIter),
Publish(<Publish<Bytes> as IntoIterator>::IntoIter),
Pubreq(<Pubrec as IntoIterator>::IntoIter),
Pubrel(<Pubrel as IntoIterator>::IntoIter),
Suback(<Suback as IntoIterator>::IntoIter),
Subscribe(<Subscribe<TopicsQosSeq, Bytes> as IntoIterator>::IntoIter),
Unsuback(<Unsuback as IntoIterator>::IntoIter),
Unsubscribe(<Unsubscribe<TopicsSeq, Bytes> as IntoIterator>::IntoIter),
}
impl<TopicsSeq, TopicsQosSeq, Bytes> Iterator for PacketIter<TopicsSeq, TopicsQosSeq, Bytes>
where
TopicsSeq: AnyVec<Bytes>,
TopicsQosSeq: AnyVec<(Bytes, u8)>,
Bytes: AnyVec<u8>,
{
type Item = u8;
fn next(&mut self) -> Option<Self::Item> {
match self {
Self::Connack(iter) => iter.next(),
Self::Connect(iter) => iter.next(),
Self::Disconnect(iter) => iter.next(),
Self::Pingreq(iter) => iter.next(),
Self::Pingresp(iter) => iter.next(),
Self::Puback(iter) => iter.next(),
Self::Pubcomp(iter) => iter.next(),
Self::Publish(iter) => iter.next(),
Self::Pubreq(iter) => iter.next(),
Self::Pubrel(iter) => iter.next(),
Self::Suback(iter) => iter.next(),
Self::Subscribe(iter) => iter.next(),
Self::Unsuback(iter) => iter.next(),
Self::Unsubscribe(iter) => iter.next(),
}
}
}