use crate::anyvec::AnyVec;
use crate::coding::encoder::{PacketLenIter, TopicsQosIter, U16Iter, U8Iter, Unit};
use crate::coding::length::Length;
use crate::coding::{Decoder, Encoder};
use crate::err;
use crate::error::{Data, DecoderError, MemoryError};
use crate::packets::TryFromIterator;
use core::iter::Chain;
use core::marker::PhantomData;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Subscribe<Seq, Bytes> {
packet_id: u16,
topics_qos: Seq,
_vec: PhantomData<Bytes>,
}
impl<Seq, Bytes> Subscribe<Seq, Bytes>
where
Seq: AnyVec<(Bytes, u8)>,
Bytes: AnyVec<u8>,
{
pub const TYPE: u8 = 8;
pub fn new<S, T>(packet_id: u16, topics: S) -> Result<Self, MemoryError>
where
S: IntoIterator<Item = (T, u8)>,
T: AsRef<[u8]>,
{
let mut topics_qos = Seq::default();
for (topic, qos) in topics {
let topic = Bytes::new(topic.as_ref())?;
topics_qos.push((topic, qos))?;
}
Ok(Self { packet_id, topics_qos, _vec: PhantomData })
}
pub fn packet_id(&self) -> u16 {
self.packet_id
}
pub fn topics_qos(&self) -> &Seq {
&self.topics_qos
}
}
impl<Seq, Bytes> TryFromIterator for Subscribe<Seq, Bytes>
where
Seq: AnyVec<(Bytes, u8)>,
Bytes: AnyVec<u8>,
{
fn try_from_iter<T>(iter: T) -> Result<Self, DecoderError>
where
T: IntoIterator<Item = u8>,
{
let mut decoder = Decoder::new(iter);
let (Self::TYPE, [false, false, true, false]) = decoder.header()? else {
return Err(err!(Data::SpecViolation, "invalid packet type/header"))?;
};
let len = decoder.packetlen()?;
let mut decoder = decoder.limit(len).peekable();
let packet_id = decoder.u16()?;
let topics_qos = decoder.topics_qos()?;
Ok(Self { packet_id, topics_qos, _vec: PhantomData })
}
}
impl<Seq, Bytes> IntoIterator for Subscribe<Seq, Bytes>
where
Seq: AnyVec<(Bytes, u8)>,
Bytes: AnyVec<u8>,
{
type Item = u8;
#[rustfmt::skip]
type IntoIter =
Chain<Chain<Chain<Chain<
Unit, U8Iter>,
PacketLenIter>,
U16Iter>,
TopicsQosIter<Seq, Bytes>>;
fn into_iter(self) -> Self::IntoIter {
#[rustfmt::skip]
let len = Length::new()
.u16(&self.packet_id)
.topics_qos(&self.topics_qos)
.into();
Encoder::default()
.header(Self::TYPE, [false, false, true, false])
.packetlen(len)
.u16(self.packet_id)
.topics_qos(self.topics_qos)
.into_iter()
}
}