rt_map/
rt_map.rs

1use std::{
2    borrow::Borrow,
3    collections::HashMap,
4    fmt,
5    hash::Hash,
6    ops::{Deref, DerefMut},
7};
8
9use rt_ref::{BorrowFail, Cell, Ref, RefMut};
10
11use crate::Entry;
12
13/// Map from `TypeId` to type.
14#[derive(Debug)]
15pub struct RtMap<K, V>(HashMap<K, Cell<V>>);
16
17impl<K, V> Default for RtMap<K, V> {
18    fn default() -> Self {
19        Self(Default::default())
20    }
21}
22
23macro_rules! borrow_panic {
24    ($key:ident) => {
25        panic!(
26            "Expected to borrow `{key:?}`, but it does not exist.",
27            key = $key
28        )
29    };
30}
31
32/// A [`HashMap`] that allows multiple mutable borrows to different entries.
33///
34/// The [`borrow`] and [`borrow_mut`] methods take `&self`, allowing multiple
35/// mutable borrows of different entries at the same time. This is achieved via
36/// interior mutability. In case you violate the borrowing rules of Rust
37/// (multiple reads xor one write), you will get a panic.
38///
39/// For non-packing versions of these methods, use [`try_borrow`] and
40/// [`try_borrow_mut`].
41///
42/// [`borrow`]: Self::borrow
43/// [`borrow_mut`]: Self::borrow_mut
44/// [`try_borrow`]: Self::try_borrow
45/// [`try_borrow_mut`]: Self::try_borrow_mut
46impl<K, V> RtMap<K, V>
47where
48    K: Hash + Eq,
49{
50    /// Creates an empty `RtMap`.
51    ///
52    /// The map is initially created with a capacity of 0, so it will not
53    /// allocate until it is first inserted into.
54    ///
55    /// # Examples
56    ///
57    /// ```rust
58    /// use rt_map::RtMap;
59    /// let mut map = RtMap::<u32, String>::new();
60    /// ```
61    pub fn new() -> Self {
62        Self::default()
63    }
64
65    /// Creates an empty `RtMap` with the specified capacity.
66    ///
67    /// The map will be able to hold at least capacity elements without
68    /// reallocating. If capacity is 0, the map will not allocate.
69    ///
70    /// # Examples
71    ///
72    /// ```rust
73    /// use rt_map::RtMap;
74    /// let map: RtMap<&str, i32> = RtMap::with_capacity(10);
75    /// ```
76    pub fn with_capacity(capacity: usize) -> Self {
77        Self(HashMap::with_capacity(capacity))
78    }
79
80    /// Returns the number of elements the map can hold without reallocating.
81    ///
82    /// This number is a lower bound; the `RtMap<K, V>` might be able to hold
83    /// more, but is guaranteed to be able to hold at least this many.
84    ///
85    /// # Examples
86    ///
87    /// ```rust
88    /// use rt_map::RtMap;
89    /// let map: RtMap<i32, i32> = RtMap::with_capacity(100);
90    /// assert!(map.capacity() >= 100);
91    /// ```
92    pub fn capacity(&self) -> usize {
93        self.0.capacity()
94    }
95
96    /// Returns the underlying map.
97    pub fn into_inner(self) -> HashMap<K, Cell<V>> {
98        self.0
99    }
100
101    /// Gets the given key’s corresponding entry in the map for in-place
102    /// manipulation.
103    pub fn entry(&mut self, k: K) -> Entry<'_, K, V> {
104        Entry::new(self.0.entry(k))
105    }
106
107    /// Inserts a key-value pair into the map.
108    ///
109    /// If the map did not have this key present, [`None`] is returned.
110    ///
111    /// If the map did have this key present, the value is updated, and the old
112    /// value is returned. The key is not updated, though; this matters for
113    /// types that can be `==` without being identical.
114    ///
115    /// # Examples
116    ///
117    /// ```rust
118    /// use rt_map::RtMap;
119    ///
120    /// let mut map = RtMap::new();
121    /// assert_eq!(map.insert(37, "a"), None);
122    /// assert_eq!(map.is_empty(), false);
123    ///
124    /// map.insert(37, "b");
125    /// assert_eq!(map.insert(37, "c"), Some("b"));
126    /// assert_eq!(*map.borrow(&37), "c");
127    /// ```
128    pub fn insert(&mut self, k: K, v: V) -> Option<V> {
129        self.0.insert(k, Cell::new(v)).map(Cell::into_inner)
130    }
131
132    /// Returns `true` if the map contains no elements.
133    ///
134    /// # Examples
135    ///
136    /// ```rust
137    /// use rt_map::RtMap;
138    ///
139    /// let mut a = RtMap::new();
140    /// assert!(a.is_empty());
141    /// a.insert(1, "a");
142    /// assert!(!a.is_empty());
143    /// ```
144    pub fn is_empty(&self) -> bool {
145        self.0.is_empty()
146    }
147
148    /// Removes a key from the map, returning the value at the key if the key
149    /// was previously in the map.
150    ///
151    /// The key may be any borrowed form of the map’s key type, but `Hash` and
152    /// `Eq` on the borrowed form must match those for the key type.
153    ///
154    /// # Examples
155    ///
156    /// ```rust
157    /// use rt_map::RtMap;
158    ///
159    /// let mut map = RtMap::new();
160    /// map.insert(1, "a");
161    /// assert_eq!(map.remove(&1), Some("a"));
162    /// assert_eq!(map.remove(&1), None);
163    /// ```
164    pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
165    where
166        Q: ?Sized + Hash + Eq,
167        K: Borrow<Q>,
168    {
169        self.0.remove(k).map(Cell::into_inner)
170    }
171
172    /// Returns `true` if the map contains a value for the specified key.
173    ///
174    /// The key may be any borrowed form of the map’s key type, but [`Hash`] and
175    /// [`Eq`] on the borrowed form must match those for the key type.
176    pub fn contains_key<Q>(&self, k: &Q) -> bool
177    where
178        Q: ?Sized + Hash + Eq,
179        K: Borrow<Q>,
180    {
181        self.0.contains_key(k)
182    }
183
184    /// Returns a reference to the value corresponding to the key.
185    ///
186    /// The key may be any borrowed form of the map’s key type, but [`Hash`] and
187    /// [`Eq`] on the borrowed form must match those for the key type.
188    ///
189    /// See [`try_borrow`] for a non-panicking version of this function.
190    ///
191    /// # Panics
192    ///
193    /// * Panics if the resource doesn't exist.
194    /// * Panics if the resource is being accessed mutably.
195    ///
196    /// [`try_borrow`]: Self::try_borrow
197    pub fn borrow<Q>(&self, k: &Q) -> Ref<V>
198    where
199        Q: ?Sized + Hash + Eq + fmt::Debug,
200        K: Borrow<Q>,
201    {
202        self.0
203            .get(k)
204            .map(|cell| Ref::new(cell.borrow()))
205            .unwrap_or_else(|| borrow_panic!(k))
206    }
207
208    /// Returns a reference to the value if it exists and is not mutably
209    /// borrowed, `None` otherwise.
210    pub fn try_borrow<Q>(&self, k: &Q) -> Result<Ref<V>, BorrowFail>
211    where
212        Q: ?Sized + Hash + Eq,
213        K: Borrow<Q>,
214    {
215        self.0
216            .get(k)
217            .ok_or(BorrowFail::ValueNotFound)
218            .and_then(|cell| cell.try_borrow().map(Ref::new))
219    }
220
221    /// Returns a reference to the value if it exists and is not borrowed,
222    /// `None` otherwise.
223    ///
224    /// # Panics
225    ///
226    /// * Panics if the resource doesn't exist.
227    /// * Panics if the resource is already accessed.
228    pub fn borrow_mut<Q>(&self, k: &Q) -> RefMut<V>
229    where
230        Q: ?Sized + Hash + Eq + fmt::Debug,
231        K: Borrow<Q>,
232    {
233        self.0
234            .get(k)
235            .map(|cell| RefMut::new(cell.borrow_mut()))
236            .unwrap_or_else(|| borrow_panic!(k))
237    }
238
239    /// Returns a mutable reference to `R` if it exists, `None` otherwise.
240    pub fn try_borrow_mut<Q>(&self, k: &Q) -> Result<RefMut<V>, BorrowFail>
241    where
242        Q: ?Sized + Hash + Eq,
243        K: Borrow<Q>,
244    {
245        self.0
246            .get(k)
247            .ok_or(BorrowFail::ValueNotFound)
248            .and_then(|r_cell| r_cell.try_borrow_mut().map(RefMut::new))
249    }
250
251    /// Retrieves a resource without fetching, which is cheaper, but only
252    /// available with `&mut self`.
253    pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
254    where
255        Q: ?Sized + Hash + Eq,
256        K: Borrow<Q>,
257    {
258        self.get_resource_mut(k)
259    }
260
261    /// Retrieves a resource without fetching, which is cheaper, but only
262    /// available with `&mut self`.
263    pub fn get_resource_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
264    where
265        Q: ?Sized + Hash + Eq,
266        K: Borrow<Q>,
267    {
268        self.0.get_mut(k).map(Cell::get_mut)
269    }
270
271    /// Get raw access to the underlying cell.
272    pub fn get_raw<Q>(&self, k: &Q) -> Option<&Cell<V>>
273    where
274        Q: ?Sized + Hash + Eq,
275        K: Borrow<Q>,
276    {
277        self.0.get(k)
278    }
279}
280
281impl<K, V> Deref for RtMap<K, V> {
282    type Target = HashMap<K, Cell<V>>;
283
284    fn deref(&self) -> &Self::Target {
285        &self.0
286    }
287}
288
289impl<K, V> DerefMut for RtMap<K, V> {
290    fn deref_mut(&mut self) -> &mut Self::Target {
291        &mut self.0
292    }
293}
294
295#[cfg(test)]
296mod tests {
297    use rt_ref::BorrowFail;
298
299    use super::RtMap;
300
301    #[derive(Debug, Default, PartialEq)]
302    struct Res;
303
304    #[derive(Debug, Default, PartialEq)]
305    struct Value(u32);
306
307    #[test]
308    fn insert() {
309        let mut rt_map = RtMap::new();
310        rt_map.insert('a', Res);
311
312        assert!(rt_map.contains_key(&'a'));
313        assert!(!rt_map.contains_key(&'b'));
314    }
315
316    #[test]
317    fn with_capacity_reserves_enough_capacity() {
318        let map: RtMap<i32, i32> = RtMap::with_capacity(100);
319        assert!(map.capacity() >= 100);
320    }
321
322    #[test]
323    fn into_inner() {
324        let mut rt_map = RtMap::new();
325        rt_map.insert('a', Res);
326        let inner_map = rt_map.into_inner();
327
328        assert!(inner_map.contains_key(&'a'));
329    }
330
331    #[test]
332    fn deref_and_deref_mut() {
333        let mut rt_map = RtMap::new();
334        rt_map.insert('a', 0);
335        rt_map.insert('b', 1);
336
337        rt_map.iter_mut().for_each(|(_k, v)| *v.borrow_mut() += 1);
338
339        let a = rt_map.remove(&'a');
340        assert_eq!(Some(1), a);
341
342        let b = rt_map.iter().next();
343        assert_eq!(Some(2), b.map(|(_k, v)| *v.borrow()));
344    }
345
346    #[test]
347    fn is_empty_returns_true_when_map_does_not_contain_items() {
348        let rt_map = RtMap::<char, u32>::new();
349
350        assert!(rt_map.is_empty());
351    }
352
353    #[test]
354    fn is_empty_returns_false_when_map_contains_items() {
355        let mut rt_map = RtMap::new();
356
357        rt_map.insert('a', 0);
358
359        assert!(!rt_map.is_empty());
360    }
361
362    #[test]
363    fn entry_insert_value() {
364        let mut rt_map = RtMap::new();
365
366        let ref_mut = rt_map.entry('a').or_insert(1);
367
368        assert_eq!(1, *ref_mut);
369        drop(ref_mut);
370
371        let ref_mut = rt_map.entry('a').or_insert(2);
372
373        assert_eq!(1, *ref_mut);
374        drop(ref_mut);
375
376        rt_map.remove(&'a');
377
378        let ref_mut = rt_map.entry('a').or_insert_with(|| 3);
379
380        assert_eq!(3, *ref_mut);
381        drop(ref_mut);
382    }
383
384    #[test]
385    fn get_mut_returns_mutable_reference_to_value() {
386        let mut rt_map = RtMap::new();
387        rt_map.insert('a', Value(1));
388
389        let value = rt_map.get_mut(&'a');
390
391        assert!(value.is_some());
392
393        if let Some(value) = value {
394            *value = Value(2);
395        }
396
397        let value = rt_map.get_mut(&'a').map(|value| value.0);
398
399        assert_eq!(Some(2), value);
400    }
401
402    #[test]
403    #[should_panic(expected = "but it was already borrowed")]
404    fn read_write_fails() {
405        let mut rt_map = RtMap::new();
406        rt_map.insert('a', Res);
407
408        let _read = rt_map.borrow(&'a');
409        let _write = rt_map.borrow_mut(&'a');
410    }
411
412    #[test]
413    #[should_panic(expected = "but it was already borrowed mutably")]
414    fn write_read_fails() {
415        let mut rt_map = RtMap::new();
416        rt_map.insert('a', Res);
417
418        let _write = rt_map.borrow_mut(&'a');
419        let _read = rt_map.borrow(&'a');
420    }
421
422    #[test]
423    fn remove_insert() {
424        let mut rt_map = RtMap::new();
425        rt_map.insert('a', Res);
426
427        assert!(rt_map.contains_key(&'a'));
428
429        rt_map.remove(&'a').unwrap();
430
431        assert!(!rt_map.contains_key(&'a'));
432
433        rt_map.insert('a', Res);
434
435        assert!(rt_map.contains_key(&'a'));
436    }
437
438    #[test]
439    #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
440    fn borrow_before_insert_panics() {
441        let rt_map = RtMap::<char, i32>::new();
442
443        rt_map.borrow(&'a');
444    }
445
446    #[test]
447    #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
448    fn borrow_mut_before_insert_panics() {
449        let rt_map = RtMap::<char, i32>::new();
450
451        rt_map.borrow_mut(&'a');
452    }
453
454    #[test]
455    fn borrow_mut_try_borrow_returns_borrow_conflict_imm() {
456        let mut rt_map = RtMap::new();
457        rt_map.insert('a', Res);
458
459        let _res = rt_map.borrow_mut(&'a');
460
461        assert_eq!(Err(BorrowFail::BorrowConflictImm), rt_map.try_borrow(&'a'));
462    }
463
464    #[test]
465    fn borrow_try_borrow_mut_returns_borrow_conflict_mut() {
466        let mut rt_map = RtMap::new();
467        rt_map.insert('a', Res);
468
469        let _res = rt_map.borrow(&'a');
470
471        assert_eq!(
472            Err(BorrowFail::BorrowConflictMut),
473            rt_map.try_borrow_mut(&'a')
474        );
475    }
476
477    #[test]
478    fn borrow_mut_borrow_mut_returns_borrow_conflict_mut() {
479        let mut rt_map = RtMap::new();
480        rt_map.insert('a', Res);
481
482        let _res = rt_map.borrow_mut(&'a');
483
484        assert_eq!(
485            Err(BorrowFail::BorrowConflictMut),
486            rt_map.try_borrow_mut(&'a')
487        );
488    }
489
490    #[test]
491    fn try_borrow_before_insert_returns_value_not_found() {
492        let rt_map = RtMap::<char, Res>::new();
493
494        assert_eq!(Err(BorrowFail::ValueNotFound), rt_map.try_borrow(&'a'));
495    }
496
497    #[test]
498    fn try_borrow_mut_before_insert_returns_value_not_found() {
499        let rt_map = RtMap::<char, Res>::new();
500
501        assert_eq!(Err(BorrowFail::ValueNotFound), rt_map.try_borrow_mut(&'a'));
502    }
503
504    #[test]
505    #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
506    fn borrow_before_insert_panics_value_not_found() {
507        let rt_map = RtMap::<char, Res>::new();
508
509        rt_map.borrow(&'a');
510    }
511
512    #[test]
513    #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
514    fn borrow_mut_before_insert_panics_value_not_found() {
515        let rt_map = RtMap::<char, Res>::new();
516
517        rt_map.borrow_mut(&'a');
518    }
519}