1#![deny(missing_docs)]
14
15use generational_arena::{Arena, Index as AIndex};
16use std::borrow::Borrow;
17use std::cell::RefCell;
18use std::collections::HashMap;
19use std::hash::Hash;
20use std::rc::Rc;
21
22mod internal_ref;
23use self::internal_ref::{InternalRef, Wrap as _};
24
25#[derive(Debug)]
27struct Entry<T> {
28 elem: Box<T>,
32 usage_cnt: Rc<RefCell<usize>>,
35}
36
37impl<T> Entry<T> {
38 fn new(elem: T) -> Self {
40 Entry {
41 elem: Box::new(elem),
42 usage_cnt: Default::default(),
43 }
44 }
45 fn cnt_handle(&self) -> Rc<RefCell<usize>> {
46 self.usage_cnt.clone()
47 }
48 fn cnt(&self) -> usize {
49 *(*self.usage_cnt).borrow()
50 }
51 fn elem(&self) -> &T {
52 self.elem.as_ref()
53 }
54}
55
56#[derive(Debug)]
58pub struct IndexedHashSet<T>
59where
60 T: 'static,
61{
62 arena: Arena<Entry<T>>,
64 map: HashMap<InternalRef<T>, AIndex>,
69}
70
71impl<T> IndexedHashSet<T>
72where
73 T: 'static + Eq + Hash,
74{
75 pub fn new() -> Self {
77 Default::default()
78 }
79 pub fn len(&self) -> usize {
81 self.arena.len()
82 }
83 pub fn get_cnt<Q>(&self, elem: &Q) -> Option<usize>
85 where
86 T: Borrow<Q>,
87 Q: ?Sized + Hash + Eq,
88 {
89 let idx = self.map.get_key_value(elem.wrap()).map(|(_, idx)| *idx)?;
90 let entry = &self.arena[idx];
91 Some(entry.cnt())
92 }
93 pub fn get_ref_by_hash<'a, Q>(&'a self, elem: &Q) -> Option<&'a T>
95 where
96 T: Borrow<Q>,
97 Q: ?Sized + Hash + Eq,
98 {
99 self.map.get_key_value(elem.wrap()).map(|(k, _)| k.as_ref())
101 }
102 pub fn get_index_by_hash<'a, Q>(&'a self, elem: &Q) -> Option<RcIndex>
104 where
105 T: Borrow<Q>,
106 Q: ?Sized + Hash + Eq,
107 {
108 let a_idx = self.map.get(elem.wrap())?;
109 Some(self.aidx_to_rcidx(*a_idx))
110 }
111 pub fn get_ref_by_index<'a>(&'a self, idx: &RcIndex) -> Option<&'a T> {
121 let entry = self.arena.get(idx.inner)?;
122 Some(entry.elem.as_ref())
123 }
124 #[must_use = "If not stored usage count of the new element goes to zero."]
133 pub fn insert(&mut self, elem: T) -> Option<RcIndex> {
134 if self.map.get(elem.wrap()).is_some() {
135 return None;
136 }
137
138 Some(self.insert_unchecked(elem))
139 }
140 pub fn get_or_insert(&mut self, elem: &T) -> RcIndex
143 where
144 T: Clone,
145 {
146 if let Some(a_idx) = self.map.get(elem.wrap()) {
147 self.aidx_to_rcidx(*a_idx)
148 } else {
149 self.insert_unchecked(elem.clone())
150 }
151 }
152 fn insert_unchecked(&mut self, elem: T) -> RcIndex {
158 let entry = Entry::new(elem);
159 let cnt_handle = entry.cnt_handle();
160 let inner_ref = InternalRef::from_ref(entry.elem());
161
162 let a_idx = self.arena.insert(entry);
163 self.map.insert(inner_ref, a_idx);
164
165 RcIndex::new(a_idx, cnt_handle)
166 }
167 pub fn drop_unused(&mut self) -> usize {
169 let arena = &mut self.arena;
171 let map = &mut self.map;
172
173 let before = arena.len();
174
175 arena.retain(|_, entry| {
176 if entry.cnt() == 0 {
177 map.remove(entry.elem().wrap());
178 false
179 } else {
180 true
181 }
182 });
183
184 before - arena.len()
185 }
186 pub fn iter(&self) -> impl Iterator<Item = &T> {
188 self.arena
189 .iter()
190 .filter_map(|(_, e)| if e.cnt() != 0 { Some(e.elem()) } else { None })
191 }
192 fn aidx_to_rcidx(&self, a_idx: AIndex) -> RcIndex {
199 let entry = &self.arena[a_idx];
200 let handle = entry.cnt_handle();
201 RcIndex::new(a_idx, handle)
202 }
203}
204
205impl<T: 'static> Default for IndexedHashSet<T> {
206 fn default() -> Self {
207 Self {
208 arena: Default::default(),
209 map: Default::default(),
210 }
211 }
212}
213
214impl<'a, T> std::ops::Index<&'a RcIndex> for IndexedHashSet<T>
218where
219 T: 'static + Eq + Hash,
220{
221 type Output = T;
222
223 fn index(&self, index: &'a RcIndex) -> &Self::Output {
224 self.get_ref_by_index(index).unwrap()
225 }
226}
227
228unsafe impl<T> Send for IndexedHashSet<T> {}
231
232#[derive(Debug)]
234pub struct RcIndex {
235 inner: AIndex,
237 cnt: Rc<RefCell<usize>>,
239}
240
241impl RcIndex {
242 fn new(idx: AIndex, cnt_handle: Rc<RefCell<usize>>) -> Self {
246 {
247 let mut cnt = cnt_handle.borrow_mut();
248 *cnt += 1;
249 }
250 Self {
251 inner: idx,
252 cnt: cnt_handle,
253 }
254 }
255 pub fn cnt(&self) -> usize {
257 *(*self.cnt).borrow()
258 }
259}
260
261impl Clone for RcIndex {
262 fn clone(&self) -> Self {
263 let mut cnt = self.cnt.borrow_mut();
264 *cnt += 1;
265 Self {
266 inner: self.inner,
267 cnt: self.cnt.clone(),
268 }
269 }
270}
271
272impl Drop for RcIndex {
273 fn drop(&mut self) {
274 let mut cnt = self.cnt.borrow_mut();
275 *cnt -= 1;
276 }
277}
278
279#[cfg(test)]
280mod tests {
281 use super::*;
282
283 fn standard_set() -> IndexedHashSet<String> {
285 let mut set = IndexedHashSet::new();
286 set.insert("Olaf".to_owned()).unwrap();
287 set.insert("Eijnar".to_owned()).unwrap();
288 set.insert("Harald".to_owned()).unwrap();
289 set
290 }
291
292 #[test]
293 fn unused_entries() {
294 let mut set = standard_set();
295 assert_eq!(set.len(), 3);
296 assert_eq!(set.drop_unused(), 3);
297 assert_eq!(set.len(), 0);
298 }
299
300 #[test]
301 fn usage_cnt() {
302 let mut set = IndexedHashSet::new();
303 let o1 = set.insert("Olaf".to_owned()).unwrap();
304 assert_eq!(o1.cnt(), 1);
305 let _o2 = set.get_index_by_hash("Olaf").unwrap();
306 assert_eq!(o1.cnt(), 2);
307 {
308 let _o3 = o1.clone();
309 assert_eq!(o1.cnt(), 3);
310 }
311 assert_eq!(o1.cnt(), 2);
312 }
313}