use alloc::vec::Vec;
use spin::Mutex;
use crate::codec::rotation_matrix::RotationMatrix;
pub const DEFAULT_CAPACITY: usize = 8;
pub struct RotationCache {
entries: Mutex<Vec<RotationMatrix>>,
capacity: usize,
}
impl RotationCache {
#[must_use]
pub const fn new(capacity: usize) -> Self {
Self {
entries: Mutex::new(Vec::new()),
capacity,
}
}
#[must_use]
pub const fn default_sized() -> Self {
Self::new(DEFAULT_CAPACITY)
}
#[inline]
#[must_use]
pub const fn capacity(&self) -> usize {
self.capacity
}
#[must_use]
pub fn len(&self) -> usize {
self.entries.lock().len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.entries.lock().is_empty()
}
pub fn get_or_build(&self, seed: u64, dimension: u32) -> RotationMatrix {
if self.capacity == 0 {
return RotationMatrix::build(seed, dimension);
}
let mut guard = self.entries.lock();
if let Some(pos) = guard
.iter()
.position(|m| m.seed() == seed && m.dimension() == dimension)
{
let touched = guard.remove(pos);
let clone = touched.clone();
guard.insert(0, touched);
return clone;
}
let built = RotationMatrix::build(seed, dimension);
if guard.len() >= self.capacity {
guard.pop();
}
guard.insert(0, built.clone());
built
}
pub fn clear(&self) {
self.entries.lock().clear();
}
}
impl Default for RotationCache {
fn default() -> Self {
Self::default_sized()
}
}
impl core::fmt::Debug for RotationCache {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.debug_struct("RotationCache")
.field("capacity", &self.capacity)
.field("entries", &self.len())
.finish()
}
}