use std::cell::RefCell; use std::cmp::Ordering; use std::collections::HashSet; use std::fmt; use std::hash::{Hash, Hasher}; use std::ops::Deref; use std::rc::Rc; pub type TabledData = Rc>>>; #[derive(Clone)] pub struct TabledRc { atom: Rc, table: TabledData } impl PartialOrd for TabledRc { fn partial_cmp(&self, other: &Self) -> Option { Some(self.atom.cmp(&other.atom)) } } impl Ord for TabledRc { fn cmp(&self, other: &Self) -> Ordering { self.atom.cmp(&other.atom) } } impl PartialEq for TabledRc { fn eq(&self, other: &TabledRc) -> bool { self.atom == other.atom } } impl Eq for TabledRc {} impl Hash for TabledRc { fn hash(&self, state: &mut H) { self.atom.hash(state) } } impl TabledRc { pub fn new(atom: T, table: TabledData) -> Self { let atom = match table.borrow_mut().take(&atom) { Some(atom) => atom.clone(), None => Rc::new(atom) }; table.borrow_mut().insert(atom.clone()); TabledRc { atom, table } } pub fn atom_tbl(&self) -> TabledData { self.table.clone() } } impl Drop for TabledRc { fn drop(&mut self) { if Rc::strong_count(&self.atom) == 2 { self.table.borrow_mut().remove(&self.atom); } } } impl Deref for TabledRc { type Target = T; fn deref(&self) -> &Self::Target { &*self.atom } } impl fmt::Display for TabledRc { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", &*self.atom) } }