#![no_std]
#[cfg(feature = "std")]
extern crate std;
mod utils;
pub(crate) use utils::*;
mod refs;
pub use refs::*;
use core::marker::PhantomPinned;
use core::ops::DerefMut;
use core::pin::Pin;
use pin_project::{pin_project, UnsafeUnpin};
use stable_deref_trait::StableDeref;
#[pin_project(UnsafeUnpin)]
pub struct SelfReference<'a, T, R>
where
R: RefDef + 'a,
{
#[pin]
referential: R::Type<'a>,
#[pin]
object: T,
__private: PhantomPinned,
}
impl<'a, T, R> SelfReference<'a, T, R>
where
R: RefDef + 'a,
{
pub fn new<F>(object: T, init: F) -> Self
where
R: 'static,
F: FnOnce() -> R::Type<'static>,
{
let referential = unsafe { detach_lifetime_ref::<R>((init)()) };
Self {
object,
referential,
__private: PhantomPinned,
}
}
pub fn new_stable<F>(mut object: T, init: F) -> Self
where
T: StableDeref + DerefMut,
F: FnOnce(&mut T::Target) -> R::Type<'_>,
{
let referential = unsafe { detach_lifetime_ref::<R>((init)(object.deref_mut())) };
Self {
object,
referential,
__private: PhantomPinned,
}
}
pub fn reset<'s, F>(self: Pin<&'s mut Self>, f: F)
where
F: FnOnce(Pin<&'s mut T>) -> R::Type<'s>,
{
let mut proj = self.project();
let value = unsafe { detach_lifetime_ref::<R>((f)(proj.object)) };
proj.referential.set(value);
}
pub fn pin_mut<'s>(self: Pin<&'s mut Self>) -> Pin<&'s mut R::Type<'s>> {
let referential = self.project().referential;
unsafe { detach_lifetime_pin_mut::<R>(referential) }
}
pub fn pin_ref<'s>(self: Pin<&'s Self>) -> Pin<&'s R::Type<'s>> {
let referential = self.project_ref().referential;
unsafe { detach_lifetime_pin_ref::<R>(referential) }
}
}
impl<'a, T, R> SelfReference<'a, T, R>
where
R: RefDef,
T: Unpin,
{
pub fn reset_unpin<'s, F>(self: Pin<&'s mut Self>, f: F)
where
F: FnOnce(&'s mut T) -> R::Type<'s>,
{
let mut proj = self.project();
let value = unsafe { detach_lifetime_ref::<R>((f)(proj.object.get_mut())) };
proj.referential.set(value);
}
}
impl<'a, T, R> SelfReference<'a, T, R>
where
R: RefDef,
T: StableDeref
{
pub fn map<'s, F, N>(self, f: F) -> SelfReference<'a, T, N>
where
for<'this> <R as refs::RefDef>::Type<'this>: Unpin,
T: 's,
R: 's,
N: RefDef + 's,
F: FnOnce(R::Type<'s>) -> N::Type<'s>,
{
let r = unsafe { detach_lifetime_ref::<R>(self.referential) };
let r = unsafe { detach_lifetime_ref::<N>((f)(r)) };
SelfReference {
object: self.object,
referential: r,
__private: PhantomPinned
}
}
pub fn get_ref<'s>(&'s self) -> &'s R::Type<'s> {
unsafe { detach_lifetime_get_ref::<R>(&self.referential) }
}
pub fn get_mut<'s>(&'s mut self) -> &'s mut R::Type<'s> {
unsafe { detach_lifetime_get_mut::<R>(&mut self.referential) }
}
pub fn into_inner(self) -> T {
self.object
}
}
unsafe impl<'a, T, R> UnsafeUnpin for SelfReference<'a, T, R>
where
R: RefDef,
T: StableDeref,
{
}