#![forbid(unsafe_code)]
use std::collections::HashMap;
use crate::core::extent::ChunkId;
use crate::rans::model::RansModel;
#[derive(Debug)]
pub struct ModelCache {
entries: HashMap<ChunkId, (RansModel, u64)>,
capacity: usize,
clock: u64,
}
impl ModelCache {
pub fn new(capacity: usize) -> Self {
Self {
entries: HashMap::new(),
capacity,
clock: 0,
}
}
pub fn get(&mut self, id: &ChunkId) -> Option<RansModel> {
let entry = self.entries.get_mut(id)?;
self.clock += 1;
entry.1 = self.clock;
Some(entry.0.clone())
}
pub fn insert(&mut self, id: ChunkId, model: RansModel) {
self.clock += 1;
self.entries.insert(id, (model, self.clock));
while self.entries.len() > self.capacity {
let victim = self
.entries
.iter()
.min_by_key(|(_, (_, rec))| *rec)
.map(|(k, _)| *k)
.expect("non-empty");
self.entries.remove(&victim);
}
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn memoizes_decoded_models() {
let mut c = ModelCache::new(4);
let data1: Vec<u8> = (0..4096u32).map(|i| (i % 3) as u8).collect();
let data2: Vec<u8> = (0..4096u32).map(|i| (i % 7) as u8).collect();
let m1 = crate::rans::model::normalize_histogram(
&crate::tests::helpers::histogram_of(&data1),
8,
crate::core::representation::RansCodec::Single,
)
.unwrap();
let m2 = crate::rans::model::normalize_histogram(
&crate::tests::helpers::histogram_of(&data2),
8,
crate::core::representation::RansCodec::Single,
)
.unwrap();
let id1 = crate::rans::metadata::model_id(&m1);
let id2 = crate::rans::metadata::model_id(&m2);
c.insert(id1, m1);
c.insert(id2, m2);
assert!(c.get(&id1).is_some());
assert!(c.get(&id2).is_some());
assert_eq!(c.len(), 2);
}
}