#![allow(unsafe_code)]
use crate::refs::*;
use crate::utils::*;
use crate::SelfieError;
use core::ops::DerefMut;
use core::pin::Pin;
use stable_deref_trait::{CloneStableDeref, StableDeref};
pub struct Selfie<'a, P, R>
where
P: 'a,
R: for<'this> RefType<'this>,
{
referential: <R as RefType<'a>>::Ref,
owned: Pin<P>,
}
impl<'a, P, R> Selfie<'a, P, R>
where
P: StableDeref + 'a,
R: for<'this> RefType<'this>,
P::Target: 'a,
{
#[inline]
pub fn new<F>(owned: Pin<P>, handler: F) -> Self
where
F: for<'this> FnOnce(&'this P::Target) -> <R as RefType<'this>>::Ref,
{
let detached = unsafe { detach_lifetime(owned.as_ref()) }.get_ref();
Self {
referential: handler(detached),
owned,
}
}
#[inline]
pub fn try_new<E, F>(owned: Pin<P>, handler: F) -> Result<Self, SelfieError<P, E>>
where
F: for<'this> FnOnce(&'this P::Target) -> Result<<R as RefType<'this>>::Ref, E>,
{
let detached = unsafe { detach_lifetime(owned.as_ref()) }.get_ref();
let referential = match handler(detached) {
Ok(r) => r,
Err(error) => return Err(SelfieError { owned, error }),
};
Ok(Self { referential, owned })
}
#[inline]
pub fn owned(&self) -> &P::Target {
self.owned.as_ref().get_ref()
}
#[inline]
pub fn with_referential<'s, F, T>(&'s self, handler: F) -> T
where
F: for<'this> FnOnce(&'s <R as RefType<'this>>::Ref) -> T,
{
let referential = unsafe { downcast_ref::<'s, 'a, R>(&self.referential) };
handler(referential)
}
#[inline]
pub fn with_referential_mut<'s, F, T>(&'s mut self, handler: F) -> T
where
F: for<'this> FnOnce(&'s mut <R as RefType<'this>>::Ref) -> T,
{
let referential = unsafe { downcast_mut::<'s, 'a, R>(&mut self.referential) };
handler(referential)
}
#[inline]
pub fn into_owned(self) -> Pin<P> {
self.owned
}
#[inline]
pub fn map<R2: for<'this> RefType<'this>, F>(self, mapper: F) -> Selfie<'a, P, R2>
where
F: for<'this> FnOnce(
<R as RefType<'this>>::Ref,
&'this P::Target,
) -> <R2 as RefType<'this>>::Ref,
{
let Self { owned, referential } = self;
let detached = unsafe { detach_lifetime(owned.as_ref()) }.get_ref();
let referential = mapper(referential, detached);
Selfie { owned, referential }
}
#[inline]
pub fn try_map<R2: for<'this> RefType<'this>, E, F>(
self,
mapper: F,
) -> Result<Selfie<'a, P, R2>, SelfieError<P, E>>
where
F: for<'this> FnOnce(
<R as RefType<'this>>::Ref,
&'this P::Target,
) -> Result<<R2 as RefType<'this>>::Ref, E>,
{
let Self { owned, referential } = self;
let detached = unsafe { detach_lifetime(owned.as_ref()) }.get_ref();
let referential = match mapper(referential, detached) {
Ok(r) => r,
Err(error) => return Err(SelfieError { owned, error }),
};
Ok(Selfie { owned, referential })
}
#[inline]
pub fn map_cloned<R2: for<'this> RefType<'this>, F>(&self, mapper: F) -> Selfie<'a, P, R2>
where
F: for<'this> FnOnce(
&<R as RefType<'this>>::Ref,
&'this P::Target,
) -> <R2 as RefType<'this>>::Ref,
P: CloneStableDeref,
{
let owned = self.owned.clone();
let detached = unsafe { detach_lifetime(owned.as_ref()) }.get_ref();
let referential = mapper(&self.referential, detached);
Selfie { owned, referential }
}
#[inline]
pub fn try_map_cloned<R2: for<'this> RefType<'this>, E, F>(
&self,
mapper: F,
) -> Result<Selfie<'a, P, R2>, E>
where
F: for<'this> FnOnce(
&<R as RefType<'this>>::Ref,
&'this P::Target,
) -> Result<<R2 as RefType<'this>>::Ref, E>,
P: CloneStableDeref,
{
let owned = self.owned.clone();
let detached = unsafe { detach_lifetime(owned.as_ref()) }.get_ref();
let referential = mapper(&self.referential, detached)?;
Ok(Selfie { owned, referential })
}
}
pub struct SelfieMut<'a, P, R>
where
P: 'a,
R: for<'this> RefType<'this>,
{
referential: <R as RefType<'a>>::Ref,
owned: Pin<P>,
}
impl<'a, P, R> SelfieMut<'a, P, R>
where
P: StableDeref + DerefMut + 'a,
R: for<'this> RefType<'this>,
{
pub fn new<F>(mut owned: Pin<P>, handler: F) -> Self
where
F: for<'this> FnOnce(Pin<&'this mut P::Target>) -> <R as RefType<'this>>::Ref,
{
let detached = unsafe { detach_lifetime_mut(owned.as_mut()) };
Self {
referential: handler(detached),
owned,
}
}
#[inline]
pub fn try_new<E, F>(mut owned: Pin<P>, handler: F) -> Result<Self, SelfieError<P, E>>
where
F: for<'this> FnOnce(Pin<&'this mut P::Target>) -> Result<<R as RefType<'this>>::Ref, E>,
{
let detached = unsafe { detach_lifetime_mut(owned.as_mut()) };
let referential = match handler(detached) {
Ok(r) => r,
Err(error) => return Err(SelfieError { owned, error }),
};
Ok(Self { referential, owned })
}
#[inline]
pub fn with_referential<'s, F, T>(&'s self, handler: F) -> T
where
F: for<'this> FnOnce(&'s <R as RefType<'this>>::Ref) -> T,
{
let referential = unsafe { downcast_ref::<'s, 'a, R>(&self.referential) };
handler(referential)
}
#[inline]
pub fn with_referential_mut<'s, F, T>(&'s mut self, handler: F) -> T
where
F: for<'this> FnOnce(&'s mut <R as RefType<'this>>::Ref) -> T,
{
let referential = unsafe { downcast_mut::<'s, 'a, R>(&mut self.referential) };
handler(referential)
}
#[inline]
pub fn into_owned(self) -> Pin<P> {
self.owned
}
#[inline]
pub fn map<R2: for<'this> RefType<'this>, F>(self, mapper: F) -> Selfie<'a, P, R2>
where
F: for<'this> FnOnce(
<R as RefType<'this>>::Ref,
&'this (), // This is needed to constrain the lifetime TODO: find a way to remove this
) -> <R2 as RefType<'this>>::Ref,
{
let Self { owned, referential } = self;
let referential = mapper(referential, &());
Selfie { owned, referential }
}
#[inline]
pub fn try_map<R2: for<'this> RefType<'this>, E, F>(
self,
mapper: F,
) -> Result<Selfie<'a, P, R2>, SelfieError<P, E>>
where
F: for<'this> FnOnce(
<R as RefType<'this>>::Ref,
&'this (), // This is needed to constrain the lifetime TODO: find a way to remove this
) -> Result<<R2 as RefType<'this>>::Ref, E>,
{
let Self { owned, referential } = self;
let referential = match mapper(referential, &()) {
Ok(r) => r,
Err(error) => return Err(SelfieError { owned, error }),
};
Ok(Selfie { owned, referential })
}
}