use std::collections::HashMap;
use std::sync::atomic::{AtomicU64, Ordering};
use crate::Element;
static NEXT_NODE_ID: AtomicU64 = AtomicU64::new(1);
fn next_node_id() -> u64 {
NEXT_NODE_ID.fetch_add(1, Ordering::Relaxed)
}
pub(crate) fn is_live<E: Element>(el: &E) -> bool {
el.is_visible().is_ok() && el.has_parent()
}
pub(crate) struct CachedNode<E> {
pub element: E,
pub id: u64,
}
pub(crate) struct NodeCache<E: Element> {
anchors: HashMap<String, CachedNode<E>>,
children: HashMap<String, HashMap<String, E>>,
parents: HashMap<String, HashMap<String, E>>,
}
impl<E: Element> NodeCache<E> {
pub fn new() -> Self {
NodeCache {
anchors: HashMap::new(),
children: HashMap::new(),
parents: HashMap::new(),
}
}
pub fn element(&self, name: &str) -> Option<&E> {
self.anchors.get(name).map(|n| &n.element)
}
pub fn node_id(&self, name: &str) -> Option<u64> {
self.anchors.get(name).map(|n| n.id)
}
pub fn anchor_is_live(&self, name: &str) -> bool {
self.anchors.get(name).is_some_and(|n| is_live(&n.element))
}
pub fn insert(&mut self, name: String, element: E) -> u64 {
let id = next_node_id();
self.anchors
.insert(name.clone(), CachedNode { element, id });
self.children.remove(&name);
self.parents.remove(&name);
id
}
pub fn anchor_names(&self) -> Vec<String> {
self.anchors.keys().cloned().collect()
}
pub fn remove(&mut self, name: &str) -> Option<CachedNode<E>> {
self.children.remove(name);
self.parents.remove(name);
self.anchors.remove(name)
}
pub fn found(&self, scope: &str, sel_key: &str) -> Option<E> {
self.children.get(scope)?.get(sel_key).cloned()
}
pub fn found_parent(&self, scope: &str, sel_key: &str) -> Option<E> {
self.parents.get(scope)?.get(sel_key).cloned()
}
pub fn set_found(&mut self, scope: &str, sel_key: String, el: E, parent: Option<E>) {
self.children
.entry(scope.to_string())
.or_default()
.insert(sel_key.clone(), el);
if let Some(p) = parent {
self.parents
.entry(scope.to_string())
.or_default()
.insert(sel_key, p);
} else {
if let Some(m) = self.parents.get_mut(scope) {
m.remove(&sel_key);
}
}
}
pub fn remove_found(&mut self, scope: &str, sel_key: &str) {
if let Some(m) = self.children.get_mut(scope) {
m.remove(sel_key);
}
if let Some(m) = self.parents.get_mut(scope) {
m.remove(sel_key);
}
}
}