use crate::Error;
use crate::codec::util::decode_word;
use crate::codec::{Decode, Encode, RawPacket};
use crate::protocol::{FixedHeader, Flags, PacketType, QoS, TopicFilters, traits};
use bytes::{BufMut, BytesMut};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Unsubscribe {
packet_id: u16,
filters: TopicFilters,
}
impl Unsubscribe {
pub fn new<T: IntoIterator<Item: Into<String>>>(packet_id: u16, filters: T) -> Self {
if packet_id == 0 {
panic!("Packet id is zero");
}
Unsubscribe {
packet_id,
filters: TopicFilters::new(filters),
}
}
pub fn packet_id(&self) -> u16 {
self.packet_id
}
pub fn filters(&self) -> TopicFilters {
self.filters.clone()
}
}
impl Decode for Unsubscribe {
fn decode(mut packet: RawPacket) -> Result<Self, Error> {
if packet.header.packet_type() != PacketType::Unsubscribe
|| packet.header.flags() != Flags::new(QoS::AtLeastOnce)
{
return Err(Error::MalformedPacket);
}
let packet_id = decode_word(&mut packet.payload)?;
let filters = TopicFilters::decode(&mut packet.payload)?;
Ok(Unsubscribe::new(packet_id, filters))
}
}
impl Encode for Unsubscribe {
fn encode(&self, buf: &mut BytesMut) -> Result<(), Error> {
let header = FixedHeader::with_flags(
PacketType::Unsubscribe,
Flags::new(QoS::AtLeastOnce),
self.payload_len(),
);
header.encode(buf)?;
buf.put_u16(self.packet_id);
self.filters.encode(buf);
Ok(())
}
fn payload_len(&self) -> usize {
2 + self.filters.encoded_len()
}
}
impl traits::Unsubscribe for Unsubscribe {}
#[cfg(test)]
mod tests {
use super::*;
use crate::codec::PacketCodec;
use bytes::BytesMut;
use tokio_util::codec::Decoder;
fn packet_data() -> &'static [u8] {
&[
(PacketType::Unsubscribe as u8) << 4 | 0b0010, 0x16, 0x12, 0x34, 0x00, 0x0c, b'h', b'e',
b'l',
b'l',
b'o',
b' ',
b'w',
b'o',
b'r',
b'l',
b'd',
b'!',
0x00, 0x04,
b't', b'e',
b's',
b't',
]
}
#[test]
fn unsubscribe_decode() {
let mut codec = PacketCodec::new(None, None);
let mut stream = BytesMut::new();
stream.extend_from_slice(packet_data());
let raw_packet = codec.decode(&mut stream).unwrap().unwrap();
let packet = Unsubscribe::decode(raw_packet).unwrap();
assert_eq!(
packet,
Unsubscribe::new(0x1234, vec!["hello world!", "test"])
);
}
#[test]
fn unsubscribe_encode() {
let packet = Unsubscribe::new(0x1234, vec!["hello world!", "test"]);
let mut stream = BytesMut::new();
packet.encode(&mut stream).unwrap();
assert_eq!(stream, Vec::from(packet_data()));
}
#[test]
#[should_panic]
fn unsubscribe_construct() {
Unsubscribe::new(0, Vec::<String>::new());
}
}