use std::{
collections::{BTreeSet, VecDeque},
sync::Mutex,
};
use crate::{
available_packet_ids::AvailablePacketIds,
error::HandlerError,
packets::{Packet, PubRel, Publish},
};
#[derive(Debug)]
pub struct State {
apkid: AvailablePacketIds,
outgoing_sub: Mutex<BTreeSet<u16>>,
outgoing_unsub: Mutex<BTreeSet<u16>>,
outgoing_pub: Mutex<Vec<Option<Publish>>>,
outgoing_pub_order: Mutex<VecDeque<u16>>,
outgoing_rel: Mutex<BTreeSet<u16>>,
incoming_pub: Mutex<BTreeSet<u16>>,
}
impl State {
pub fn new(receive_maximum: u16, apkid: AvailablePacketIds) -> Self {
Self {
apkid,
outgoing_sub: Mutex::new(BTreeSet::new()),
outgoing_unsub: Mutex::new(BTreeSet::new()),
outgoing_pub: Mutex::new(vec![None; receive_maximum as usize]),
outgoing_pub_order: Mutex::new(VecDeque::new()),
outgoing_rel: Mutex::new(BTreeSet::new()),
incoming_pub: Mutex::new(BTreeSet::new()),
}
}
pub fn make_pkid_available(&self, pkid: u16) -> Result<(), HandlerError> {
self.apkid.mark_available(pkid)
}
pub fn add_incoming_pub(&self, pkid: u16) -> bool {
self.incoming_pub.lock().unwrap().insert(pkid)
}
pub fn remove_incoming_pub(&self, pkid: u16) -> bool {
self.incoming_pub.lock().unwrap().remove(&pkid)
}
pub fn add_outgoing_pub(&self, pkid: u16, publish: Publish) -> Result<(), HandlerError> {
let mut outgoing_pub = self.outgoing_pub.lock().unwrap();
let current_pub = outgoing_pub[(pkid - 1) as usize].replace(publish);
if current_pub.is_some() {
Err(HandlerError::PacketIdCollision(pkid))
} else {
let mut outgoing_pub_order = self.outgoing_pub_order.lock().unwrap();
outgoing_pub_order.push_back(pkid);
Ok(())
}
}
pub fn remove_outgoing_pub(&self, pkid: u16) -> Option<Publish> {
{
let mut outgoing_pub_order = self.outgoing_pub_order.lock().unwrap();
for (index, id) in outgoing_pub_order.iter().enumerate() {
if pkid == *id {
outgoing_pub_order.remove(index);
break;
}
}
}
let mut outgoing_pub = self.outgoing_pub.lock().unwrap();
outgoing_pub[pkid as usize - 1].take()
}
pub fn add_outgoing_rel(&self, pkid: u16) -> bool {
self.outgoing_rel.lock().unwrap().insert(pkid)
}
pub fn remove_outgoing_rel(&self, pkid: &u16) -> bool {
self.outgoing_rel.lock().unwrap().remove(pkid)
}
pub fn add_outgoing_sub(&self, pkid: u16) -> bool {
self.outgoing_sub.lock().unwrap().insert(pkid)
}
pub fn remove_outgoing_sub(&self, pkid: u16) -> bool {
self.outgoing_sub.lock().unwrap().remove(&pkid)
}
pub fn add_outgoing_unsub(&self, pkid: u16) -> bool {
self.outgoing_unsub.lock().unwrap().insert(pkid)
}
pub fn remove_outgoing_unsub(&self, pkid: u16) -> bool {
self.outgoing_unsub.lock().unwrap().remove(&pkid)
}
pub fn reset(&self, retransmission: bool) -> (Vec<u16>, Vec<Packet>) {
let State {
apkid: _,
outgoing_sub,
outgoing_unsub,
outgoing_pub,
outgoing_pub_order,
outgoing_rel,
incoming_pub,
} = self;
let mut outgoing_sub = outgoing_sub.lock().unwrap();
let mut outgoing_unsub = outgoing_unsub.lock().unwrap();
let mut outgoing_pub = outgoing_pub.lock().unwrap();
let mut outgoing_pub_order = outgoing_pub_order.lock().unwrap();
let mut outgoing_rel = outgoing_rel.lock().unwrap();
let mut incoming_pub = incoming_pub.lock().unwrap();
let mut freeable_ids = Vec::<u16>::with_capacity(outgoing_sub.len() + outgoing_unsub.len());
let mut retransmit = Vec::with_capacity(outgoing_pub_order.len());
freeable_ids.extend(outgoing_sub.iter());
freeable_ids.extend(outgoing_unsub.iter());
if retransmission {
for i in outgoing_pub_order.iter() {
let mut packet = outgoing_pub[(*i - 1) as usize].clone().unwrap();
packet.dup = true;
retransmit.push(Packet::Publish(packet));
}
for &rel in outgoing_rel.iter() {
retransmit.push(Packet::PubRel(PubRel::new(rel)));
}
} else {
freeable_ids.extend(outgoing_pub_order.iter());
*outgoing_pub = vec![None; outgoing_pub.len()];
outgoing_pub_order.clear();
outgoing_rel.clear();
}
outgoing_sub.clear();
outgoing_unsub.clear();
incoming_pub.clear();
(freeable_ids, retransmit)
}
}
#[cfg(test)]
impl State {
pub fn outgoing_sub(&mut self) -> std::sync::MutexGuard<'_, BTreeSet<u16>> {
self.outgoing_sub.lock().unwrap()
}
pub fn outgoing_unsub(&mut self) -> std::sync::MutexGuard<'_, BTreeSet<u16>> {
self.outgoing_unsub.lock().unwrap()
}
pub fn outgoing_pub(&mut self) -> std::sync::MutexGuard<'_, Vec<Option<Publish>>> {
self.outgoing_pub.lock().unwrap()
}
pub fn outgoing_pub_order(&mut self) -> std::sync::MutexGuard<'_, VecDeque<u16>> {
self.outgoing_pub_order.lock().unwrap()
}
pub fn outgoing_rel(&mut self) -> std::sync::MutexGuard<'_, BTreeSet<u16>> {
self.outgoing_rel.lock().unwrap()
}
pub fn incoming_pub(&mut self) -> std::sync::MutexGuard<'_, BTreeSet<u16>> {
self.incoming_pub.lock().unwrap()
}
}