restor/black_box/
map.rs

1use parking_lot::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
2use std::cell::{Ref, RefMut};
3use std::ops::{Deref, DerefMut};
4
5///
6/// A trait forcing the implementor to implement a `map` function
7/// this is used to genericize over `MappedMutexGuard`,
8/// `MappedRwLockReadGuard` and `Ref`
9///
10pub trait Map<I: ?Sized, O: ?Sized>: Deref<Target = I> + Sized {
11    type Output: Deref<Target = O>;
12    type Func: ?Sized + 'static;
13    fn map(self, f: &Self::Func) -> Self::Output;
14}
15
16impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> Map<I, O> for Ref<'a, I> {
17    type Output = Ref<'a, O>;
18    type Func = dyn for<'b> Fn(&'b I) -> &'b O;
19    fn map(self, f: &Self::Func) -> Ref<'a, O> {
20        Ref::map(self, f)
21    }
22}
23
24impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> Map<I, O> for MappedRwLockReadGuard<'a, I> {
25    type Output = MappedRwLockReadGuard<'a, O>;
26    type Func = dyn for<'b> Fn(&'b I) -> &'b O;
27    fn map(self, f: &Self::Func) -> MappedRwLockReadGuard<'a, O> {
28        MappedRwLockReadGuard::map(self, f)
29    }
30}
31
32///
33/// A trait forcing the implementor to implement a `map` method
34/// this is used to genericize over `MappedMutexGuard` and
35/// `MappedRwLockWriteGuard` and `RefMut`
36///
37pub trait MapMut<I: ?Sized, O: ?Sized>: Deref<Target = I> + Sized + DerefMut {
38    type Output: Deref<Target = O> + DerefMut;
39    type Func: ?Sized + 'static;
40    fn map(self, f: &Self::Func) -> Self::Output;
41}
42
43impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> MapMut<I, O> for RefMut<'a, I> {
44    type Output = RefMut<'a, O>;
45    type Func = dyn for<'b> Fn(&'b mut I) -> &'b mut O;
46    fn map(self, f: &Self::Func) -> RefMut<'a, O> {
47        RefMut::map(self, f)
48    }
49}
50
51impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> MapMut<I, O> for MappedRwLockWriteGuard<'a, I> {
52    type Output = MappedRwLockWriteGuard<'a, O>;
53    type Func = dyn for<'b> Fn(&'b mut I) -> &'b mut O;
54    fn map(self, f: &Self::Func) -> MappedRwLockWriteGuard<'a, O> {
55        MappedRwLockWriteGuard::map(self, f)
56    }
57}
58
59impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> MapMut<I, O> for MappedMutexGuard<'a, I> {
60    type Output = MappedMutexGuard<'a, O>;
61    type Func = dyn for<'b> Fn(&'b mut I) -> &'b mut O;
62    fn map(self, f: &Self::Func) -> MappedMutexGuard<'a, O> {
63        MappedMutexGuard::map(self, f)
64    }
65}
66
67#[cfg(test)]
68mod tests {
69    use super::{Map, MapMut};
70    use crate::{make_storage, RwLockStorage};
71    use lazy_static::*;
72    lazy_static! {
73        static ref storage: RwLockStorage = make_storage!(RwLockStorage: UnMut, Mut);
74    }
75    #[derive(Debug)]
76    struct UnMut(pub String);
77
78    #[derive(Debug)]
79    struct Mut(pub String);
80
81    #[test]
82    fn test_map() {
83        storage.insert(UnMut("Abc".into())).unwrap();
84        let guard = storage.get::<&UnMut>().unwrap();
85        assert_eq!(guard.0, "Abc");
86        let guard = guard.map(&|x| &x.0[1..]);
87        assert_eq!(&*guard, "bc");
88    }
89
90    #[test]
91    fn test_map_mut() {
92        storage.insert(Mut("Abc".into())).unwrap();
93        let mut guard = storage.get::<&mut Mut>().unwrap();
94        assert_eq!(guard.0, "Abc");
95        guard.0.push_str("def");
96        let guard = guard.map(&|x| &mut x.0[2..]);
97        assert_eq!(&*guard, "cdef");
98    }
99}