use std::cell::RefCell; use std::collections::HashMap; use std::hash::Hash; use std::rc::Rc; /// A shared mutable hash map managed by reference counting. /// /// # Cloning /// /// The `Clone` trait implements cloning of the map by reference. /// Use the `clone_content()` method to clone the map by content. /// /// # Equality /// /// The `PartialEq` trait performs reference comparison of two maps. /// /// # Hashing /// /// The `Hash` trait performs hashing of the map by reference. /// /// # Iteration /// /// To iterate a `SharedMap`, it is required to invoke the `borrow()` method, /// as in the following snippet: /// /// ```ignore /// map_object.borrow().iter(|(k, v)| { /// // k: &K /// // v: &V /// }); /// ``` #[derive(Clone)] pub struct SharedMap(Rc>>); impl PartialEq for SharedMap { fn eq(&self, other: &Self) -> bool { Rc::ptr_eq(&self.0, &other.0) } } impl Eq for SharedMap {} impl Hash for SharedMap { /// Performs hashing of the map by reference. fn hash(&self, state: &mut H) { self.0.as_ptr().hash(state) } } impl SharedMap { pub fn new() -> Self { Self(Rc::new(RefCell::new(HashMap::new()))) } pub fn get(&self, key: &K) -> Option where K: Eq + Hash, V: Clone { self.0.borrow().get(key).map(|v| v.clone()) } pub fn set(&mut self, key: K, value: V) where K: Eq + Hash { self.0.borrow_mut().insert(key, value); } pub fn remove(&mut self, key: &K) -> Option where K: Eq + Hash { self.0.borrow_mut().remove(key) } pub fn has(&self, key: &K) -> bool where K: Eq + Hash { self.0.borrow().contains_key(key) } pub fn length(&self) -> usize { self.0.borrow().len() } pub fn clone_content(&self) -> Self where K: Clone + Eq + Hash, V: Clone { let mut r = Self::new(); for (k, v) in self.borrow().iter() { r.set(k.clone(), v.clone()); } r } pub fn borrow(&self) -> std::cell::Ref> { self.0.borrow() } } impl From<[(K, V); N]> for SharedMap { fn from(value: [(K, V); N]) -> Self { Self::from_iter(value) } } impl From> for SharedMap { fn from(value: Vec<(K, V)>) -> Self { Self::from_iter(value) } } impl From> for SharedMap { fn from(value: HashMap) -> Self { Self::from_iter(value) } } impl FromIterator<(K, V)> for SharedMap { fn from_iter>(iter: T2) -> Self { let mut r = Self::new(); for (k, v) in iter { r.set(k, v); } r } } impl<'a, K: Eq + Hash + Clone, V: Clone> FromIterator<(&'a K, &'a V)> for SharedMap { fn from_iter>(iter: T2) -> Self { let mut r = Self::new(); for (k, v) in iter { r.set(k.clone(), v.clone()); } r } } impl Extend<(K, V)> for SharedMap where K: Eq + Hash { fn extend>(&mut self, iter: T) { for (k, v) in iter.into_iter() { self.set(k, v); } } } pub macro shared_map { ($($key:expr => $value:expr),*) => { SharedMap::from([$(($key, $value)),*]) }, ($($key:expr => $value:expr),+ ,) => { SharedMap::from([$(($key, $value)),+]) }, }