use std::collections::{HashMap, HashSet};
#[derive(Debug)]
pub struct DependencyTracker {
cache_to_views: HashMap<String, Vec<String>>,
view_to_caches: HashMap<String, HashSet<String>>,
}
impl DependencyTracker {
#[must_use]
pub fn new() -> Self {
Self {
cache_to_views: HashMap::new(),
view_to_caches: HashMap::new(),
}
}
#[allow(clippy::needless_pass_by_value)] pub fn record_access(&mut self, cache_key: String, views: Vec<String>) {
if let Some(old_views) = self.cache_to_views.get(&cache_key) {
for old_view in old_views {
if let Some(caches) = self.view_to_caches.get_mut(old_view) {
caches.remove(&cache_key);
if caches.is_empty() {
self.view_to_caches.remove(old_view);
}
}
}
}
self.cache_to_views.insert(cache_key.clone(), views.clone());
for view in views {
self.view_to_caches.entry(view).or_default().insert(cache_key.clone());
}
}
#[must_use]
pub fn get_dependent_caches(&self, view: &str) -> Vec<String> {
self.view_to_caches
.get(view)
.map(|set| set.iter().cloned().collect())
.unwrap_or_default()
}
pub fn remove_cache(&mut self, cache_key: &str) {
if let Some(views) = self.cache_to_views.remove(cache_key) {
for view in views {
if let Some(caches) = self.view_to_caches.get_mut(&view) {
caches.remove(cache_key);
if caches.is_empty() {
self.view_to_caches.remove(&view);
}
}
}
}
}
pub fn clear(&mut self) {
self.cache_to_views.clear();
self.view_to_caches.clear();
}
#[must_use]
pub fn cache_count(&self) -> usize {
self.cache_to_views.len()
}
#[must_use]
pub fn view_count(&self) -> usize {
self.view_to_caches.len()
}
#[must_use]
pub fn get_all_views(&self) -> Vec<String> {
self.view_to_caches.keys().cloned().collect()
}
}
impl Default for DependencyTracker {
fn default() -> Self {
Self::new()
}
}