Skip to main content

adar_registry/
registry_map.rs

1use super::{
2    entry::{Entry, EntryId},
3    registry::RegistryInterface,
4};
5use std::{
6    any::Any,
7    cmp::Ord,
8    collections::BTreeMap,
9    fmt::{self, Debug},
10    sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard, Weak},
11};
12
13#[derive(Debug)]
14pub enum RegistryMapError {
15    KeyAlreadyExists,
16}
17
18impl fmt::Display for RegistryMapError {
19    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20        write!(f, "Key already exists in registry!")
21    }
22}
23
24impl std::error::Error for RegistryMapError {}
25
26/// [`RegistryMap`] is a map whose registered elements' lifetimes are controlled by the non-copyable [`Entry`] object.
27pub struct RegistryMap<K, T>
28where
29    T: Send + Sync + 'static,
30    K: Ord,
31{
32    inner: Arc<RwLock<Inner<K, T>>>,
33}
34
35// Note: Derive macro is not used here in order to make the implementation independent from T
36impl<K, T> Default for RegistryMap<K, T>
37where
38    T: Send + Sync,
39    K: Ord + Send + Sync + Clone + 'static,
40{
41    fn default() -> Self {
42        RegistryMap::new()
43    }
44}
45
46// Note: Derive macro is not used here in order to make the implementation independent from T
47impl<K, T> Clone for RegistryMap<K, T>
48where
49    T: Send + Sync,
50    K: Ord,
51{
52    fn clone(&self) -> Self {
53        Self {
54            inner: self.inner.clone(),
55        }
56    }
57}
58
59impl<K, T> Debug for RegistryMap<K, T>
60where
61    T: Send + Sync + Debug,
62    K: Send + Sync + Clone + Ord + Debug + 'static,
63{
64    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
65        self.read().guard.map.fmt(f)
66    }
67}
68
69impl<K, T> RegistryMap<K, T>
70where
71    T: Send + Sync,
72    K: Ord + Send + Sync + Clone + 'static,
73{
74    /// Creates a new RegistryMap.
75    pub fn new() -> Self {
76        RegistryMap {
77            inner: Arc::new(RwLock::new(Inner {
78                map: BTreeMap::new(),
79                entry_map: BTreeMap::new(),
80                next_id: 0,
81                remove_callback: None,
82            })),
83        }
84    }
85
86    /// Registers an element in the [`RegistryMap`].
87    ///
88    /// # Returns
89    /// [`Entry`] which controls the lifetime of the registered element. If the key already exists, `None` is returned.
90    #[must_use = "Entry will be immediately revoked if not used"]
91    pub fn register(&self, key: K, value: T) -> Result<Entry<T>, RegistryMapError> {
92        let mut lock = self.inner.write().unwrap();
93
94        if lock.map.contains_key(&key) {
95            return Err(RegistryMapError::KeyAlreadyExists);
96        }
97
98        let entry_id = lock.next_id;
99        lock.map.insert(key.clone(), value);
100        lock.entry_map.insert(entry_id, key);
101        lock.next_id += 1;
102
103        Ok(Entry::<T>::new(
104            Arc::downgrade(&self.inner) as Weak<RwLock<dyn RegistryInterface + 'static>>,
105            entry_id,
106        ))
107    }
108
109    /// Creates a [`RegistryMapReadGuard`] which can be used to read the contents of the RegistryMap.
110    pub fn read(&self) -> RegistryMapReadGuard<K, T> {
111        RegistryMapReadGuard::<K, T> {
112            guard: self.inner.read().unwrap(),
113        }
114    }
115
116    /// Creates a [`RegistryMapWriteGuard`] which can be used to write the contents of the RegistryMap.
117    pub fn write(&self) -> RegistryMapWriteGuard<K, T> {
118        RegistryMapWriteGuard::<K, T> {
119            guard: self.inner.write().unwrap(),
120        }
121    }
122
123    /// Returns the number of elements in the RegistryMap.
124    pub fn len(&self) -> usize {
125        self.inner.read().unwrap().map.len()
126    }
127
128    /// Returns true if the RegistryMap contains no elements.
129    pub fn is_empty(&self) -> bool {
130        self.inner.read().unwrap().map.is_empty()
131    }
132
133    /// Sets a remove callback for the RegistryMap. \
134    /// Note: If you call this multiple times. It will override the previous callback.
135    pub fn set_remove_callback<C>(&self, callback: C)
136    where
137        C: FnMut(EntryId, K, T) + Send + Sync + 'static,
138    {
139        self.inner.write().unwrap().remove_callback = Some(Box::new(callback))
140    }
141}
142
143#[derive(Default)]
144struct Inner<K, T>
145where
146    T: Send + Sync,
147{
148    map: BTreeMap<K, T>,
149    entry_map: BTreeMap<EntryId, K>,
150    next_id: EntryId,
151    remove_callback: Option<Box<dyn FnMut(EntryId, K, T) + Send + Sync>>,
152}
153
154impl<K, T> RegistryInterface for Inner<K, T>
155where
156    T: Send + Sync + 'static,
157    K: Send + Sync + Ord,
158{
159    fn get(&self, entry_id: u32) -> Option<&dyn Any> {
160        let Some(key) = self.entry_map.get(&entry_id) else {
161            return None;
162        };
163        if let Some(value) = self.map.get(key) {
164            Some(value)
165        } else {
166            None
167        }
168    }
169    fn get_mut(&mut self, entry_id: EntryId) -> Option<&mut dyn Any> {
170        let Some(key) = self.entry_map.get(&entry_id) else {
171            return None;
172        };
173        if let Some(value) = self.map.get_mut(key) {
174            Some(value)
175        } else {
176            None
177        }
178    }
179    fn remove(&mut self, entry_id: EntryId) {
180        let key = self
181            .entry_map
182            .remove(&entry_id)
183            .expect("Failed to find key for EntryId during removal!");
184        if let Some(value) = self.map.remove(&key) {
185            if let Some(callback) = &mut self.remove_callback {
186                callback(entry_id, key, value);
187            }
188        }
189    }
190}
191
192/// Holds a read guard to the RegistryMap. See [`RegistryMap::read()`].
193pub struct RegistryMapReadGuard<'a, K, T>
194where
195    T: Send + Sync,
196{
197    guard: RwLockReadGuard<'a, Inner<K, T>>,
198}
199
200impl<'a, K, T> RegistryMapReadGuard<'a, K, T>
201where
202    T: Send + Sync,
203    K: Ord,
204{
205    /// Acquires an iterator over the RegistryMap.
206    pub fn iter(&'a self) -> std::collections::btree_map::Iter<'a, K, T> {
207        self.guard.map.iter()
208    }
209
210    /// Acquires a reference to an element from the RegistryMap.
211    pub fn get(&self, key: &K) -> Option<&T> {
212        self.guard.map.get(key)
213    }
214}
215
216/// Holds a write guard to the RegistryMap. See [`RegistryMap::write()`].
217pub struct RegistryMapWriteGuard<'a, K, T>
218where
219    T: Send + Sync,
220{
221    guard: RwLockWriteGuard<'a, Inner<K, T>>,
222}
223
224impl<'a, K, T> RegistryMapWriteGuard<'a, K, T>
225where
226    T: Send + Sync,
227    K: Ord,
228{
229    /// Acquires an iterator over the RegistryMap.
230    pub fn iter(&'a self) -> std::collections::btree_map::Iter<'a, K, T> {
231        self.guard.map.iter()
232    }
233
234    /// Acquires a mutable iterator over the RegistryMap.
235    pub fn iter_mut(&mut self) -> std::collections::btree_map::IterMut<'_, K, T> {
236        self.guard.map.iter_mut()
237    }
238
239    /// Acquires a reference to an element in the RegistryMap.
240    pub fn get(&self, key: &K) -> Option<&T> {
241        self.guard.map.get(key)
242    }
243
244    /// Acquires a mutable reference to an element in the RegistryMap.
245    pub fn get_mut(&mut self, key: &K) -> Option<&mut T> {
246        self.guard.map.get_mut(key)
247    }
248}