use std::collections::HashMap;
use reovim_arch::sync::ArcSwap;
#[derive(Debug)]
pub struct LineCache<T> {
inner: ArcSwap<HashMap<usize, (u64, T)>>,
}
impl<T: Clone + Send + Sync + 'static> LineCache<T> {
#[must_use]
pub fn new() -> Self {
Self {
inner: ArcSwap::from_pointee(HashMap::new()),
}
}
#[must_use]
pub fn has(&self, line_idx: usize, hash: u64) -> bool {
self.inner
.load()
.get(&line_idx)
.is_some_and(|(h, _)| *h == hash)
}
#[must_use]
pub fn get_if_valid(&self, line_idx: usize, hash: u64) -> Option<T> {
self.inner
.load()
.get(&line_idx)
.filter(|(h, _)| *h == hash)
.map(|(_, v)| v.clone())
}
#[must_use]
pub fn get(&self, line_idx: usize) -> Option<(u64, T)> {
self.inner.load().get(&line_idx).cloned()
}
pub fn store(&self, entries: HashMap<usize, (u64, T)>) {
self.inner.rcu(move |_current| entries.clone());
}
pub fn update(&self, updates: &HashMap<usize, (u64, T)>) {
let updates = updates.clone();
self.inner.rcu(move |current| {
let mut new_map = (**current).clone();
new_map.extend(updates.clone());
new_map
});
}
#[must_use]
pub fn clone_entries(&self) -> HashMap<usize, (u64, T)> {
(**self.inner.load()).clone()
}
pub fn invalidate_from(&self, from_line: usize) {
self.inner.rcu(|current| {
let filtered: HashMap<usize, (u64, T)> = current
.iter()
.filter(|(idx, _)| **idx < from_line)
.map(|(k, v)| (*k, v.clone()))
.collect();
filtered
});
}
pub fn invalidate_line(&self, line_idx: usize) {
self.inner.rcu(|current| {
let mut new_map = (**current).clone();
new_map.remove(&line_idx);
new_map
});
}
pub fn clear(&self) {
self.inner.rcu(|_| HashMap::new());
}
#[must_use]
pub fn len(&self) -> usize {
self.inner.load().len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.inner.load().is_empty()
}
#[must_use]
pub fn cached_lines(&self) -> Vec<usize> {
self.inner.load().keys().copied().collect()
}
}
impl<T: Clone + Send + Sync + 'static> Default for LineCache<T> {
fn default() -> Self {
Self::new()
}
}