use core::ops::{Deref, DerefMut};
impl<Source> super::AccessAs for Source {
fn ref_as<T: ?Sized>(&self) -> <Self as IGuardRef<T>>::Guard<'_>
where
Self: IGuardRef<T>,
{
self.guard_ref_inner()
}
fn mut_as<T: ?Sized>(&mut self) -> <Self as IGuardMut<T>>::GuardMut<'_>
where
Self: IGuardMut<T>,
{
self.guard_mut_inner()
}
}
pub trait IGuardRef<T: ?Sized> {
type Guard<'a>: Deref<Target = T>
where
Self: 'a;
fn guard_ref_inner(&self) -> Self::Guard<'_>;
}
pub trait IGuardMut<T: ?Sized>: IGuardRef<T> {
type GuardMut<'a>: DerefMut<Target = T>
where
Self: 'a;
fn guard_mut_inner(&mut self) -> Self::GuardMut<'_>;
}
pub struct RefAs<'a, T, As> {
source: core::marker::PhantomData<&'a T>,
target: core::mem::ManuallyDrop<As>,
}
impl<'a, T, As> Deref for RefAs<'a, T, As> {
type Target = As;
fn deref(&self) -> &Self::Target {
&self.target
}
}
impl<T: Into<As>, As: Into<T>> IGuardRef<As> for T {
type Guard<'a> = RefAs<'a, T, As> where Self: 'a;
fn guard_ref_inner(&self) -> Self::Guard<'_> {
RefAs {
source: core::marker::PhantomData,
target: core::mem::ManuallyDrop::new(unsafe { core::ptr::read(self).into() }),
}
}
}
pub struct MutAs<'a, T, As: Into<T>> {
source: &'a mut T,
target: core::mem::ManuallyDrop<As>,
}
impl<'a, T, As: Into<T>> Deref for MutAs<'a, T, As> {
type Target = As;
fn deref(&self) -> &Self::Target {
&self.target
}
}
impl<'a, T, As: Into<T>> DerefMut for MutAs<'a, T, As> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.target
}
}
impl<'a, T, As: Into<T>> Drop for MutAs<'a, T, As> {
fn drop(&mut self) {
unsafe { core::ptr::write(self.source, core::ptr::read(&*self.target).into()) }
}
}
impl<T: Into<As>, As: Into<T>> IGuardMut<As> for T {
type GuardMut<'a> = MutAs<'a, T, As> where Self: 'a;
fn guard_mut_inner(&mut self) -> Self::GuardMut<'_> {
MutAs {
target: core::mem::ManuallyDrop::new(unsafe { core::ptr::read(self).into() }),
source: self,
}
}
}