wachter_storage/
handle_map.rs

1use core::hash::Hash;
2use std::{collections::HashMap, marker::PhantomData};
3
4#[derive(Debug)]
5pub struct Handle<V> {
6    handle: usize,
7    marker: PhantomData<V>,
8}
9
10// We have to impl all these traits by hand because of
11// https://github.com/rust-lang/rust/issues/26925
12impl<V> Handle<V> {
13    fn new(handle: usize) -> Self {
14        Self {
15            handle,
16            marker: PhantomData,
17        }
18    }
19}
20
21impl<V> PartialEq for Handle<V> {
22    fn eq(&self, other: &Self) -> bool {
23        self.handle == other.handle
24    }
25}
26
27impl<V> Eq for Handle<V> {}
28impl<V> Hash for Handle<V> {
29    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
30        state.write_usize(self.handle)
31    }
32}
33impl<V> Clone for Handle<V> {
34    fn clone(&self) -> Self {
35        Handle::new(self.handle)
36    }
37}
38impl<V> Copy for Handle<V> {}
39
40#[derive(Debug)]
41pub struct HandleMap<V> {
42    // TODO This could be a Vec
43    storage: HashMap<Handle<V>, V>,
44}
45
46impl<V> HandleMap<V> {
47    pub fn new() -> Self {
48        Self {
49            storage: HashMap::new(),
50        }
51    }
52
53    pub fn insert(&mut self, value: V) -> Handle<V> {
54        self.register(value)
55    }
56
57    pub fn get(&self, handle: Handle<V>) -> Option<&V> {
58        self.storage.get(&handle)
59    }
60
61    pub fn get_mut(&mut self, handle: Handle<V>) -> Option<&mut V> {
62        self.storage.get_mut(&handle)
63    }
64
65    pub fn remove(&mut self, handle: Handle<V>) -> Option<V> {
66        self.storage.remove(&handle)
67    }
68
69    fn register(&mut self, value: V) -> Handle<V> {
70        let id = self.storage.len();
71        let handle = Handle::new(id);
72        self.storage.insert(handle, value);
73        handle
74    }
75}
76
77#[cfg(test)]
78mod test {
79    use super::*;
80
81    #[test]
82    fn insert_and_retrieve() {
83        let mut map: HandleMap<String> = HandleMap::new();
84        let hello = "Hello".to_string();
85        let handle_1 = map.insert(hello.clone());
86        let _ = map.insert("World".to_string());
87        let res = map.get(handle_1);
88        assert!(res.is_some());
89        assert_eq!(&hello, res.unwrap());
90    }
91
92    #[test]
93    fn get_missing() {
94        let mut map: HandleMap<String> = HandleMap::new();
95        let hello = "Hello".to_string();
96        let handle_1 = map.insert(hello.clone());
97        map.remove(handle_1);
98        let res = map.get(handle_1);
99        assert!(res.is_none());
100    }
101}