use std::{
cell::UnsafeCell,
ops::{self},
};
pub trait DerefExt: ops::Deref {
fn deref_map<F, R>(self, f: F) -> MapDeref<Self, F>
where
Self: Sized,
F: Fn(&Self::Target) -> &R,
{
MapDeref { deref: self, f }
}
}
pub struct MapDeref<T, F> {
deref: T,
f: F,
}
impl<T, F, R> ops::Deref for MapDeref<T, F>
where
F: Fn(&T::Target) -> &R,
T: ops::Deref,
{
type Target = R;
fn deref(&self) -> &Self::Target {
(self.f)(self.deref.deref())
}
}
impl<T> DerefExt for T where T: ops::Deref {}
pub trait DerefMutExt: ops::DerefMut {
fn deref_mut_map<F, R>(self, f: F) -> MapDerefMut<Self, F>
where
Self: Sized,
F: Fn(&mut Self::Target) -> &mut R,
{
MapDerefMut {
deref: UnsafeCell::new(self),
f,
}
}
}
pub struct MapDerefMut<T, F> {
deref: UnsafeCell<T>,
f: F,
}
impl<T, F, R> ops::Deref for MapDerefMut<T, F>
where
F: Fn(&mut T::Target) -> &mut R,
T: ops::DerefMut,
{
type Target = R;
fn deref(&self) -> &Self::Target {
(self.f)(unsafe { &mut *self.deref.get() })
}
}
impl<T, F, R> ops::DerefMut for MapDerefMut<T, F>
where
F: Fn(&mut T::Target) -> &mut R,
T: ops::DerefMut,
{
fn deref_mut(&mut self) -> &mut Self::Target {
(self.f)(unsafe { &mut *self.deref.get() })
}
}
impl<T> DerefMutExt for T where T: ops::DerefMut {}