hydroperfox_smodel/util/
shared_map.rs

1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::hash::Hash;
4use std::rc::Rc;
5
6/// A shared mutable hash map managed by reference counting.
7/// 
8/// # Cloning
9/// 
10/// The `Clone` trait implements cloning of the map by reference.
11/// Use the `clone_content()` method to clone the map by content.
12/// 
13/// # Equality
14/// 
15/// The `PartialEq` trait performs reference comparison of two maps.
16///
17/// # Hashing
18/// 
19/// The `Hash` trait performs hashing of the map by reference.
20///
21/// # Iteration
22/// 
23/// To iterate a `SharedMap`, it is required to invoke the `borrow()` method,
24/// as in the following snippet:
25/// 
26/// ```ignore
27/// for (k, v) in map_object.borrow().iter() {
28///     // k: &K
29///     // v: &V
30/// }
31/// ```
32#[derive(Clone)]
33pub struct SharedMap<K, V>(Rc<RefCell<HashMap<K, V>>>);
34
35impl<K, V> PartialEq for SharedMap<K, V> {
36    fn eq(&self, other: &Self) -> bool {
37        Rc::ptr_eq(&self.0, &other.0)
38    }
39}
40
41impl<K, V> Eq for SharedMap<K, V> {}
42
43impl<K, V> Hash for SharedMap<K, V> {
44    /// Performs hashing of the map by reference.
45    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
46        self.0.as_ptr().hash(state)
47    }
48}
49
50impl<K, V> SharedMap<K, V> {
51    pub fn new() -> Self {
52        Self(Rc::new(RefCell::new(HashMap::new())))
53    }
54
55    pub fn get(&self, key: &K) -> Option<V> where K: Eq + Hash, V: Clone {
56        self.0.borrow().get(key).map(|v| v.clone())
57    }
58
59    pub fn set(&mut self, key: K, value: V) where K: Eq + Hash {
60        self.0.borrow_mut().insert(key, value);
61    }
62
63    pub fn remove(&mut self, key: &K) -> Option<V> where K: Eq + Hash {
64        self.0.borrow_mut().remove(key)
65    }
66
67    pub fn clear(&mut self) {
68        self.0.borrow_mut().clear();
69    }
70
71    pub fn has(&self, key: &K) -> bool where K: Eq + Hash {
72        self.0.borrow().contains_key(key)
73    }
74
75    pub fn length(&self) -> usize {
76        self.0.borrow().len()
77    }
78
79    pub fn clone_content(&self) -> Self where K: Clone + Eq + Hash, V: Clone {
80        let mut r = Self::new();
81        for (k, v) in self.borrow().iter() {
82            r.set(k.clone(), v.clone());
83        }
84        r
85    }
86
87    pub fn borrow(&self) -> std::cell::Ref<HashMap<K, V>> {
88        self.0.borrow()
89    }
90
91    pub fn borrow_mut(&mut self) -> std::cell::RefMut<HashMap<K, V>> {
92        self.0.borrow_mut()
93    }
94}
95
96impl<const N: usize, K: Eq + Hash, V> From<[(K, V); N]> for SharedMap<K, V> {
97    fn from(value: [(K, V); N]) -> Self {
98        Self::from_iter(value)
99    }
100}
101
102impl<K: Eq + Hash, V> From<Vec<(K, V)>> for SharedMap<K, V> {
103    fn from(value: Vec<(K, V)>) -> Self {
104        Self::from_iter(value)
105    }
106}
107
108impl<K: Eq + Hash, V> From<HashMap<K, V>> for SharedMap<K, V> {
109    fn from(value: HashMap<K, V>) -> Self {
110        Self::from_iter(value)
111    }
112}
113
114impl<K: Eq + Hash, V> FromIterator<(K, V)> for SharedMap<K, V> {
115    fn from_iter<T2: IntoIterator<Item = (K, V)>>(iter: T2) -> Self {
116        let mut r = Self::new();
117        for (k, v) in iter {
118            r.set(k, v);
119        }
120        r
121    }
122}
123
124impl<'a, K: Eq + Hash + Clone, V: Clone> FromIterator<(&'a K, &'a V)> for SharedMap<K, V> {
125    fn from_iter<T2: IntoIterator<Item = (&'a K, &'a V)>>(iter: T2) -> Self {
126        let mut r = Self::new();
127        for (k, v) in iter {
128            r.set(k.clone(), v.clone());
129        }
130        r
131    }
132}
133
134impl<K, V> Extend<(K, V)> for SharedMap<K, V> where K: Eq + Hash {
135    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
136        for (k, v) in iter.into_iter() {
137            self.set(k, v);
138        }
139    }
140}
141
142#[macro_export]
143macro_rules! shared_map {
144    ($($key:expr => $value:expr),*) => {
145        SharedMap::from([$(($key, $value)),*])
146    };
147    ($($key:expr => $value:expr),+ ,) => {
148        SharedMap::from([$(($key, $value)),+])
149    };
150}