use std::collections::HashMap;
use std::sync::{Arc, Mutex, PoisonError};
use super::parent_chain::ParentChainIndex;
use super::types::{AccessRule, EntityKind, EntityRow};
#[derive(Debug)]
pub(super) struct EntityRules {
pub(super) entity: Option<EntityRow>,
pub(super) rules: Vec<AccessRule>,
}
type EntityKey = (EntityKind, String);
#[derive(Debug, Default)]
struct Slot {
index: Option<Arc<ParentChainIndex>>,
entries: HashMap<EntityKey, Arc<EntityRules>>,
}
#[derive(Debug, Default)]
pub(super) struct EntityRulesCache {
slot: Mutex<Slot>,
}
impl EntityRulesCache {
pub(super) fn get(
&self,
index: &Arc<ParentChainIndex>,
kind: EntityKind,
id: &str,
) -> Option<Arc<EntityRules>> {
let mut slot = self.slot.lock().unwrap_or_else(PoisonError::into_inner);
if !slot
.index
.as_ref()
.is_some_and(|held| Arc::ptr_eq(held, index))
{
slot.index = Some(Arc::clone(index));
slot.entries.clear();
return None;
}
slot.entries.get(&(kind, id.to_owned())).cloned()
}
pub(super) fn insert(
&self,
index: &Arc<ParentChainIndex>,
kind: EntityKind,
id: &str,
value: EntityRules,
) -> Arc<EntityRules> {
let value = Arc::new(value);
let mut slot = self.slot.lock().unwrap_or_else(PoisonError::into_inner);
if slot
.index
.as_ref()
.is_some_and(|held| Arc::ptr_eq(held, index))
{
slot.entries
.insert((kind, id.to_owned()), Arc::clone(&value));
}
value
}
}