use crate::{waker, Family, Never, TopScope};
use std::{
future::Future,
marker::PhantomData,
mem::MaybeUninit,
pin::Pin,
ptr::{addr_of_mut, NonNull},
task::Poll,
};
pub struct FrozenFuture<'a, 'b, T>
where
T: for<'c> Family<'c>,
'b: 'a,
{
mut_ref: State<T>,
state: *mut State<T>,
marker: PhantomData<&'a mut <T as Family<'b>>::Family>,
}
pub struct TimeCapsule<T>
where
T: for<'a> Family<'a>,
{
pub(crate) state: *mut State<T>,
}
impl<T> Clone for TimeCapsule<T>
where
T: for<'a> Family<'a>,
{
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for TimeCapsule<T> where T: for<'a> Family<'a> {}
impl<T> TimeCapsule<T>
where
T: for<'a> Family<'a>,
{
pub fn freeze<'a, 'b>(
&'a mut self,
t: &'a mut <T as Family<'b>>::Family,
) -> FrozenFuture<'a, 'b, T>
where
'b: 'a,
{
FrozenFuture {
mut_ref: Some(NonNull::from(t).cast()),
state: self.state,
marker: PhantomData,
}
}
pub async fn freeze_forever<'a, 'b>(
&'a mut self,
t: &'a mut <T as Family<'b>>::Family,
) -> Never {
loop {
self.freeze(t).await
}
}
}
pub(crate) type State<T> = Option<NonNull<<T as Family<'static>>::Family>>;
#[repr(C)]
pub(crate) struct RawScope<T, F: ?Sized>
where
T: for<'a> Family<'a>,
{
state: State<T>,
active_fut: F,
}
impl<T, F> RawScope<T, F>
where
T: for<'a> Family<'a>,
{
pub fn new_uninit() -> RawScope<T, MaybeUninit<F>> {
RawScope {
state: None,
active_fut: MaybeUninit::uninit(),
}
}
}
struct RawScopeFields<T, F: ?Sized>
where
T: for<'a> Family<'a>,
{
state: *mut State<T>,
active_fut: *mut F,
}
impl<T, F: ?Sized> RawScope<T, F>
where
T: for<'a> Family<'a>,
{
unsafe fn fields(this: *mut Self) -> RawScopeFields<T, F> {
RawScopeFields {
state: unsafe { addr_of_mut!((*this).state) },
active_fut: unsafe { addr_of_mut!((*this).active_fut) },
}
}
}
impl<T, F> RawScope<T, F>
where
T: for<'a> Family<'a>,
F: Future<Output = Never>,
{
pub(crate) unsafe fn open<S: TopScope<Family = T, Future = F>>(this: *mut Self, scope: S)
where
T: for<'a> Family<'a>,
F: Future<Output = Never>,
S: TopScope<Family = T>,
{
let RawScopeFields { state, active_fut } = unsafe { Self::fields(this) };
let time_capsule = TimeCapsule { state };
unsafe {
active_fut.write(scope.run(time_capsule));
}
}
}
impl<T, F: ?Sized> RawScope<T, F>
where
T: for<'a> Family<'a>,
F: Future<Output = Never>,
{
#[allow(unused_unsafe)]
pub(crate) unsafe fn enter<'borrow, Output, G>(this: NonNull<Self>, f: G) -> Output
where
G: for<'a> FnOnce(&'borrow mut <T as Family<'a>>::Family) -> Output,
{
let RawScopeFields { state, active_fut } = unsafe { Self::fields(this.as_ptr()) };
let active_fut: Pin<&mut F> = unsafe { Pin::new_unchecked(&mut *active_fut) };
match active_fut.poll(&mut std::task::Context::from_waker(&waker::create())) {
Poll::Ready(never) => match never {},
Poll::Pending => {}
}
let mut_ref = unsafe {
state
.read()
.expect("The scope's future did not fill the value")
.as_mut()
};
f(mut_ref)
}
}
impl<'a, 'b, T> Future for FrozenFuture<'a, 'b, T>
where
T: for<'c> Family<'c>,
{
type Output = ();
fn poll(
mut self: std::pin::Pin<&mut Self>,
_cx: &mut std::task::Context<'_>,
) -> Poll<Self::Output> {
let state: &mut State<T> = unsafe { &mut *self.state };
if state.is_none() {
let mut_ref = self
.mut_ref
.take()
.expect("poll called several times on the same future");
*state = Some(mut_ref);
Poll::Pending
} else {
*state = None;
Poll::Ready(())
}
}
}