use std::{future::Future, marker::PhantomData};
use crate::{Family, Never, TimeCapsule};
pub(crate) trait Sealed {}
impl<P, Family, Future, Output> Sealed for Wrapper<P, Family, Future, Output>
where
P: FnOnce(super::TimeCapsule<Family>) -> Future,
Family: for<'a> crate::Family<'a>,
Future: std::future::Future<Output = Output>,
{
}
#[allow(private_bounds)]
pub trait Scope: Sealed {
type Family: for<'a> Family<'a>;
type Output;
type Future: Future<Output = Self::Output>;
unsafe fn run(self, time_capsule: TimeCapsule<Self::Family>) -> Self::Future;
}
pub trait TopScope: Scope<Output = Never> {}
impl<S> TopScope for S where S: Scope<Output = Never> {}
struct Wrapper<P, Family, Future, Output>(P, PhantomData<*const Family>)
where
P: FnOnce(TimeCapsule<Family>) -> Future,
Family: for<'a> crate::Family<'a>,
Future: std::future::Future<Output = Output>;
impl<P, Family, Future, Output> Scope for Wrapper<P, Family, Future, Output>
where
P: FnOnce(TimeCapsule<Family>) -> Future,
Family: for<'a> crate::Family<'a>,
Future: std::future::Future<Output = Output>,
{
type Family = Family;
type Output = Output;
type Future = Future;
unsafe fn run(self, time_capsule: TimeCapsule<Self::Family>) -> Self::Future {
(self.0)(time_capsule)
}
}
#[doc(hidden)]
pub unsafe fn new_scope<P, Family, Future, Output>(
producer: P,
) -> impl Scope<Family = Family, Output = Output, Future = Future>
where
P: FnOnce(TimeCapsule<Family>) -> Future,
Family: for<'a> crate::Family<'a>,
Future: std::future::Future<Output = Output>,
{
Wrapper(producer, PhantomData)
}
#[macro_export]
macro_rules! scope {
($b:block) => {
match move |#[allow(unused_variables, unused_mut)] mut time_capsule| async move {
'check_top: {
#[allow(unreachable_code)]
if false {
break 'check_top (loop {});
}
#[allow(unused_macros)]
macro_rules! freeze {
($e:expr) => {
#[allow(unreachable_code)]
if false {
break 'check_top (loop {});
}
$crate::TimeCapsule::freeze(&mut time_capsule, $e).await
}
}
#[allow(unused_macros)]
macro_rules! freeze_forever {
($e:expr) => {{
#[allow(unreachable_code)]
if false {
break 'check_top (loop {});
}
$crate::TimeCapsule::freeze_forever(&mut time_capsule, $e).await}
}
}
#[allow(unused_macros)]
macro_rules! sub_scope {
($e:expr) => {{
#[allow(unreachable_code)]
if false {
break 'check_top (loop {});
}
match $e { e => unsafe { $crate::scope::Scope::run(e, time_capsule).await } }
}}
}
$b
}
} { scope => unsafe { $crate::scope::new_scope(scope) } }
};
}