use crate::mqtt::common::tracing::trace;
use crate::mqtt::common::IndexMap;
use crate::mqtt::packet::GenericStorePacket;
use crate::mqtt::packet::IsPacketId;
use crate::mqtt::packet::ResponsePacket;
use crate::mqtt::result_code::MqttError;
use alloc::vec::Vec;
pub struct GenericStore<PacketIdType: IsPacketId> {
map: IndexMap<PacketIdType, GenericStorePacket<PacketIdType>>,
}
pub type Store = GenericStore<u16>;
impl<PacketIdType: IsPacketId> GenericStore<PacketIdType> {
pub fn new() -> Self {
Self {
map: IndexMap::default(),
}
}
pub fn add(&mut self, packet: GenericStorePacket<PacketIdType>) -> Result<(), MqttError> {
let id = packet.packet_id();
if self.map.contains_key(&id) {
return Err(MqttError::PacketIdentifierConflict);
}
self.map.insert(id, packet);
Ok(())
}
pub fn erase(&mut self, response: ResponsePacket, packet_id: PacketIdType) -> bool {
if let Some((index, _, pkt)) = self.map.get_full(&packet_id) {
if pkt.response_packet() == response {
self.map.shift_remove_index(index);
return true;
}
}
false
}
pub fn erase_publish(&mut self, packet_id: PacketIdType) -> bool {
if let Some((index, _, pkt)) = self.map.get_full(&packet_id) {
if matches!(
pkt.response_packet(),
ResponsePacket::V3_1_1Puback
| ResponsePacket::V3_1_1Pubrec
| ResponsePacket::V5_0Puback
| ResponsePacket::V5_0Pubrec
) {
self.map.shift_remove_index(index);
return true;
}
}
false
}
pub fn clear(&mut self) {
self.map.clear();
}
pub fn for_each<F>(&mut self, mut func: F)
where
F: FnMut(&GenericStorePacket<PacketIdType>) -> bool,
{
let mut to_remove = Vec::new();
for (id, pkt) in &self.map {
if !func(pkt) {
to_remove.push(*id);
}
}
for id in to_remove {
self.map.shift_remove(&id);
trace!("[store] removed pid: {id:?}");
}
}
pub fn get_stored(&self) -> Vec<GenericStorePacket<PacketIdType>> {
self.map.values().cloned().collect()
}
}