use parking_lot::{MappedMutexGuard, MappedRwLockReadGuard, MappedRwLockWriteGuard};
use std::cell::{Ref, RefMut};
use std::ops::{Deref, DerefMut};
pub trait Map<I: ?Sized, O: ?Sized>: Deref<Target = I> + Sized {
type Output: Deref<Target = O>;
type Func: ?Sized + 'static;
fn map(self, f: &Self::Func) -> Self::Output;
}
impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> Map<I, O> for Ref<'a, I> {
type Output = Ref<'a, O>;
type Func = dyn for<'b> Fn(&'b I) -> &'b O;
fn map(self, f: &Self::Func) -> Ref<'a, O> {
Ref::map(self, f)
}
}
impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> Map<I, O> for MappedRwLockReadGuard<'a, I> {
type Output = MappedRwLockReadGuard<'a, O>;
type Func = dyn for<'b> Fn(&'b I) -> &'b O;
fn map(self, f: &Self::Func) -> MappedRwLockReadGuard<'a, O> {
MappedRwLockReadGuard::map(self, f)
}
}
pub trait MapMut<I: ?Sized, O: ?Sized>: Deref<Target = I> + Sized + DerefMut {
type Output: Deref<Target = O> + DerefMut;
type Func: ?Sized + 'static;
fn map(self, f: &Self::Func) -> Self::Output;
}
impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> MapMut<I, O> for RefMut<'a, I> {
type Output = RefMut<'a, O>;
type Func = dyn for<'b> Fn(&'b mut I) -> &'b mut O;
fn map(self, f: &Self::Func) -> RefMut<'a, O> {
RefMut::map(self, f)
}
}
impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> MapMut<I, O> for MappedRwLockWriteGuard<'a, I> {
type Output = MappedRwLockWriteGuard<'a, O>;
type Func = dyn for<'b> Fn(&'b mut I) -> &'b mut O;
fn map(self, f: &Self::Func) -> MappedRwLockWriteGuard<'a, O> {
MappedRwLockWriteGuard::map(self, f)
}
}
impl<'a, I: 'static + ?Sized, O: 'static + ?Sized> MapMut<I, O> for MappedMutexGuard<'a, I> {
type Output = MappedMutexGuard<'a, O>;
type Func = dyn for<'b> Fn(&'b mut I) -> &'b mut O;
fn map(self, f: &Self::Func) -> MappedMutexGuard<'a, O> {
MappedMutexGuard::map(self, f)
}
}
#[cfg(test)]
mod tests {
use super::{Map, MapMut};
use crate::{make_storage, RwLockStorage};
use lazy_static::*;
lazy_static! {
static ref storage: RwLockStorage = make_storage!(RwLockStorage: UnMut, Mut);
}
#[derive(Debug)]
struct UnMut(pub String);
#[derive(Debug)]
struct Mut(pub String);
#[test]
fn test_map() {
storage.insert(UnMut("Abc".into())).unwrap();
let guard = storage.get::<&UnMut>().unwrap();
assert_eq!(guard.0, "Abc");
let guard = guard.map(&|x| &x.0[1..]);
assert_eq!(&*guard, "bc");
}
#[test]
fn test_map_mut() {
storage.insert(Mut("Abc".into())).unwrap();
let mut guard = storage.get::<&mut Mut>().unwrap();
assert_eq!(guard.0, "Abc");
guard.0.push_str("def");
let guard = guard.map(&|x| &mut x.0[2..]);
assert_eq!(&*guard, "cdef");
}
}