use std::future::Future;
use std::pin::Pin;
type PinnedFut<'a, R> = Pin<Box<dyn Future<Output = R> + Send + 'a>>;
type FutGen<A, R> = Box<dyn for<'a> FnOnce(&'a mut A) -> PinnedFut<'a, R> + Send>;
#[macro_export]
macro_rules! job {
( |$a:ident$(: $t:ty)?| $b:stmt ) => {
$crate::Job::new(Box::new(|$a$(: $t)?| Box::pin(async move { $b })))
};
( |$a:ident$(: $t:ty)?| $b:tt ) => {
$crate::Job::new(Box::new(|$a$(: $t)?| Box::pin(async move $b)))
};
( move |$a:ident$(: $t:ty)?| $b:stmt ) => {
$crate::Job::new(Box::new(move |$a$(: $t)?| Box::pin(async move { $b })))
};
( move |$a:ident$(: $t:ty)?| $b:tt ) => {
$crate::Job::new(Box::new(move |$a$(: $t)?| Box::pin(async move $b)))
};
}
pub struct Job<A, R>(FutGen<A, R>);
impl<A, R> Job<A, R> {
pub fn new(f: FutGen<A, R>) -> Self {
Self(f)
}
pub async fn with(self, a: &mut A) -> R {
(self.0)(a).await
}
}