extern crate evmap;
extern crate parking_lot;
use self::evmap::ShallowCopy;
use self::parking_lot::Mutex;
pub type Keytype = u64;
#[derive(Hash, Eq, PartialEq)]
pub struct HierarchyIndexer {
last_index: Keytype,
}
impl HierarchyIndexer {
pub fn new() -> Self {
Self { last_index: 1 } }
pub fn get_index(&mut self) -> Keytype {
self.last_index += 1;
self.last_index
}
}
pub struct AdjHashMap {
pub r: evmap::ReadHandle<Keytype, Keytype>,
pub w: Mutex<evmap::WriteHandle<Keytype, Keytype>>,
indexer: HierarchyIndexer,
}
impl AdjHashMap {
pub fn new() -> Self {
let (r, mut w) = evmap::new();
Self {
r,
w: Mutex::new(w),
indexer: HierarchyIndexer::new(),
}
}
pub fn exists(&self, index: &Keytype) -> bool {
if *index == 0u64 {
return true;
}
self.r.get(index).is_some()
}
pub fn insert_entity(&mut self, parent: &Keytype) -> Option<Keytype> {
if !self.exists(parent) {
return None;
}
let mut hierarchy_w = self.w.lock();
let new_index: Keytype = self.indexer.get_index();
hierarchy_w.insert(parent.clone(), new_index);
hierarchy_w.refresh();
Some(new_index)
}
pub fn insert_parent(&mut self, children: &[Keytype]) -> Option<Keytype> {
let mut hierarchy_w = self.w.lock();
let parent: Keytype = self.indexer.get_index();
for child in children {
hierarchy_w.insert(parent.clone(), child.clone());
}
hierarchy_w.refresh();
Some(parent)
}
}
pub mod utils {
pub enum RecursiveOpError<E> {
NotFound(),
OpError(E),
}
impl<E> RecursiveOpError<E> {
pub fn map_to_op(self, mapper: fn(Self) -> E) -> E {
if let Self::OpError(e) = self {
e
} else {
mapper(self)
}
}
}
use super::*;
pub fn move_children(
hierarchy: &mut AdjHashMap,
old_parent: &Keytype,
new_parent: &Keytype,
) -> bool {
let mut hierarchy_w = hierarchy.w.lock();
let hierarchy_r = &hierarchy.r;
if !hierarchy.exists(new_parent) {
return false;
}
for child in hierarchy_r.get(&old_parent).unwrap().iter() {
hierarchy_w.insert(new_parent.clone(), (*child).clone());
}
hierarchy_w.clear(old_parent.clone());
hierarchy_w.flush();
true
}
pub fn recursive_op<E>(
hierarchy: &AdjHashMap,
parent: &Keytype,
pre_op: Option<&Fn(&Keytype) -> Result<(), E>>,
post_op: Option<&Fn(&Keytype) -> Result<(), E>>,
) -> Result<(), RecursiveOpError<E>> {
let hierarchy_r = &hierarchy.r.clone();
if !hierarchy.exists(parent) {
return Err(RecursiveOpError::NotFound());
}
if hierarchy_r.get(parent).unwrap().is_empty() {
return Ok(());
}
for child in hierarchy_r.get(parent).unwrap().iter() {
if let Some(pre_op) = pre_op {
if let Err(error) = pre_op(child) {
return Err(RecursiveOpError::OpError(error));
}
}
recursive_op(hierarchy, child, pre_op, post_op);
if let Some(post_op) = post_op {
if let Err(error) = post_op(child) {
return Err(RecursiveOpError::OpError(error));
}
}
}
Ok(())
}
pub fn recursive_delete(
hierarchy: &mut AdjHashMap,
parent: &Keytype,
on_removed: &Fn(&Keytype),
) -> bool {
let hierarchy_r = &hierarchy.r.clone();
if !hierarchy.exists(parent) {
return false;
}
if hierarchy_r.get(parent).unwrap().is_empty() {
return true;
}
for child in hierarchy_r.get(parent).unwrap().iter() {
on_removed(child);
recursive_delete(hierarchy, child, on_removed);
}
let mut hierarchy_w = hierarchy.w.lock();
hierarchy_w.clear(parent.clone());
true
}
}