use crate::{
ByteArray, DecodeError, DecodePacket, EncodeError, EncodePacket, FixedHeader, Packet, PacketId,
PacketType, QoS, VarIntError,
};
#[repr(u8)]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
pub enum SubscribeAck {
QoS(QoS),
#[default]
Failed,
}
#[allow(clippy::module_name_repetitions)]
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct SubscribeAckPacket {
packet_id: PacketId,
acknowledgements: Vec<SubscribeAck>,
}
impl SubscribeAckPacket {
#[must_use]
pub fn new(packet_id: PacketId, ack: SubscribeAck) -> Self {
Self {
packet_id,
acknowledgements: vec![ack],
}
}
#[must_use]
pub fn with_vec(packet_id: PacketId, acknowledgements: Vec<SubscribeAck>) -> Self {
Self {
packet_id,
acknowledgements,
}
}
pub fn set_packet_id(&mut self, packet_id: PacketId) -> &mut Self {
self.packet_id = packet_id;
self
}
#[must_use]
pub const fn packet_id(&self) -> PacketId {
self.packet_id
}
pub fn set_ack(&mut self, ack: &[SubscribeAck]) -> &mut Self {
self.acknowledgements.clear();
self.acknowledgements.extend(ack);
self
}
#[must_use]
pub fn acknowledgements(&self) -> &[SubscribeAck] {
&self.acknowledgements
}
fn get_fixed_header(&self) -> Result<FixedHeader, VarIntError> {
let remaining_length = PacketId::bytes() + QoS::bytes() * self.acknowledgements.len();
FixedHeader::new(PacketType::SubscribeAck, remaining_length)
}
}
impl DecodePacket for SubscribeAckPacket {
fn decode(ba: &mut ByteArray) -> Result<Self, DecodeError> {
let fixed_header = FixedHeader::decode(ba)?;
if fixed_header.packet_type() != PacketType::SubscribeAck {
return Err(DecodeError::InvalidPacketType);
}
let packet_id = PacketId::decode(ba)?;
let mut acknowledgements = Vec::new();
let mut remaining_length = PacketId::bytes();
while remaining_length < fixed_header.remaining_length() {
let payload = ba.read_byte()?;
remaining_length += QoS::bytes();
match payload & 0b1000_0011 {
0b1000_0000 => acknowledgements.push(SubscribeAck::Failed),
0b0000_0010 => acknowledgements.push(SubscribeAck::QoS(QoS::ExactOnce)),
0b0000_0001 => acknowledgements.push(SubscribeAck::QoS(QoS::AtLeastOnce)),
0b0000_0000 => acknowledgements.push(SubscribeAck::QoS(QoS::AtMostOnce)),
_ => return Err(DecodeError::InvalidQoS),
}
}
Ok(Self {
packet_id,
acknowledgements,
})
}
}
impl EncodePacket for SubscribeAckPacket {
fn encode(&self, buf: &mut Vec<u8>) -> Result<usize, EncodeError> {
let old_len = buf.len();
let fixed_header = self.get_fixed_header()?;
fixed_header.encode(buf)?;
self.packet_id.encode(buf)?;
for ack in &self.acknowledgements {
let flag = {
match *ack {
SubscribeAck::Failed => 0b1000_0000,
SubscribeAck::QoS(qos) => qos as u8,
}
};
buf.push(flag);
}
Ok(buf.len() - old_len)
}
}
impl Packet for SubscribeAckPacket {
fn packet_type(&self) -> PacketType {
PacketType::SubscribeAck
}
fn bytes(&self) -> Result<usize, VarIntError> {
let fixed_header = self.get_fixed_header()?;
Ok(fixed_header.bytes() + fixed_header.remaining_length())
}
}