1use parking_lot::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
2use std::cell::{Ref, RefMut};
3use std::ops::{Deref, DerefMut};
4
5pub 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
32pub 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}