use crate::time::Microseconds32;
use crate::OutOfMemoryError;
use alloc::collections::BTreeMap;
use core::fmt::Debug;
use heapless::LinearMap;
pub trait SessionTracker<N, T, D> {
fn get(&self, node: N) -> Option<&Session<T, D>>;
fn get_mut(&mut self, node: N) -> Option<&mut Session<T, D>>;
fn get_mut_or_insert_with<F>(
&mut self,
node: N,
generator: F,
) -> Result<&mut Session<T, D>, OutOfMemoryError>
where
N: Clone,
F: FnOnce() -> Session<T, D>;
fn insert(&mut self, node: N, session: Session<T, D>) -> Result<(), OutOfMemoryError>;
fn remove(&mut self, node: N);
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Session<T, D> {
Active(ActiveSession<T, D>),
Complete {
time: Microseconds32,
transfer_id: T,
},
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct ActiveSession<T, D> {
pub time: Microseconds32,
pub transfer_id: T,
pub data: D,
}
pub struct SessionLinearMap<N, T, D, const C: usize> {
sessions: LinearMap<N, Session<T, D>, C>,
}
impl<N, T, D, const C: usize> SessionTracker<N, T, D> for SessionLinearMap<N, T, D, C>
where
N: Eq,
N: Clone,
{
fn get(&self, node: N) -> Option<&Session<T, D>> {
self.sessions.get(&node)
}
fn get_mut(&mut self, node: N) -> Option<&mut Session<T, D>> {
self.sessions.get_mut(&node)
}
fn get_mut_or_insert_with<F>(
&mut self,
node: N,
generator: F,
) -> Result<&mut Session<T, D>, OutOfMemoryError>
where
N: Clone,
F: FnOnce() -> Session<T, D>,
{
if !self.sessions.contains_key(&node) {
self.sessions
.insert(node.clone(), generator())
.map_err(|_| OutOfMemoryError)?;
}
Ok(self.sessions.get_mut(&node).unwrap())
}
fn insert(&mut self, node: N, session: Session<T, D>) -> Result<(), OutOfMemoryError> {
self.sessions
.insert(node, session)
.map(drop)
.map_err(|_| OutOfMemoryError)
}
fn remove(&mut self, node: N) {
self.sessions.remove(&node);
}
}
pub struct SessionArray<T, D, const C: usize> {
sessions: [Option<Session<T, D>>; C],
}
impl<N, T, D, const C: usize> SessionTracker<N, T, D> for SessionArray<T, D, C>
where
N: Into<usize>,
{
fn get(&self, node: N) -> Option<&Session<T, D>> {
self.sessions[node.into()].as_ref()
}
fn get_mut(&mut self, node: N) -> Option<&mut Session<T, D>> {
self.sessions[node.into()].as_mut()
}
fn get_mut_or_insert_with<F>(
&mut self,
node: N,
generator: F,
) -> Result<&mut Session<T, D>, OutOfMemoryError>
where
N: Clone,
F: FnOnce() -> Session<T, D>,
{
let entry = &mut self.sessions[node.into()];
if entry.is_none() {
*entry = Some(generator());
}
Ok(entry.as_mut().unwrap())
}
fn insert(&mut self, node: N, session: Session<T, D>) -> Result<(), OutOfMemoryError> {
self.sessions[node.into()] = Some(session);
Ok(())
}
fn remove(&mut self, node: N) {
self.sessions[node.into()] = None;
}
}
pub struct SessionDynamicMap<N, T, D> {
sessions: BTreeMap<N, Session<T, D>>,
}
impl<N, T, D> Default for SessionDynamicMap<N, T, D>
where
N: Ord,
{
fn default() -> Self {
SessionDynamicMap {
sessions: BTreeMap::default(),
}
}
}
impl<N, T, D> SessionTracker<N, T, D> for SessionDynamicMap<N, T, D>
where
N: Ord + Clone + Debug,
{
fn get(&self, node: N) -> Option<&Session<T, D>> {
self.sessions.get(&node)
}
fn get_mut(&mut self, node: N) -> Option<&mut Session<T, D>> {
self.sessions.get_mut(&node)
}
fn get_mut_or_insert_with<F>(
&mut self,
node: N,
generator: F,
) -> Result<&mut Session<T, D>, OutOfMemoryError>
where
N: Clone,
F: FnOnce() -> Session<T, D>,
{
Ok(self.sessions.entry(node).or_insert_with(generator))
}
fn insert(&mut self, node: N, session: Session<T, D>) -> Result<(), OutOfMemoryError> {
let _ = self.sessions.insert(node, session);
Ok(())
}
fn remove(&mut self, node: N) {
self.sessions.remove(&node);
}
}