use crate::{
fib::{self, Fiber},
future::fallback::*,
};
use core::{future::Future, pin::Pin};
type SessFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;
pub trait ProcLoop: Send + 'static {
type Context: Context<Self::Req, Self::ReqRes>;
type Cmd: Send + 'static;
type CmdRes: Send + 'static;
type Req: Send + 'static;
type ReqRes: Send + 'static;
const STACK_SIZE: usize;
fn run_cmd(cmd: Self::Cmd, context: Self::Context) -> Self::CmdRes;
#[inline]
fn on_create() {}
#[inline]
fn on_enter() {}
#[inline]
fn on_drop() {}
}
pub trait Sess: Send {
type ProcLoop: ProcLoop;
type Fiber: Fiber<
Input = In<<Self::ProcLoop as ProcLoop>::Cmd, <Self::ProcLoop as ProcLoop>::ReqRes>,
Yield = Out<<Self::ProcLoop as ProcLoop>::Req, <Self::ProcLoop as ProcLoop>::CmdRes>,
Return = !,
> + Send;
type Error: Send;
fn fib(&mut self) -> Pin<&mut Self::Fiber>;
fn run_req(
&mut self,
req: <Self::ProcLoop as ProcLoop>::Req,
) -> SessFuture<'_, Result<<Self::ProcLoop as ProcLoop>::ReqRes, Self::Error>>;
fn cmd(
&mut self,
cmd: <Self::ProcLoop as ProcLoop>::Cmd,
) -> SessFuture<'_, Result<<Self::ProcLoop as ProcLoop>::CmdRes, Self::Error>> {
let mut input = In { cmd };
Box::pin(asyn(move || {
loop {
let fib::Yielded(output) = self.fib().resume(input);
input = match output {
Out::Req(req) => In {
req_res: awt!(self.run_req(req))?,
},
Out::CmdRes(res) => break Ok(res),
}
}
}))
}
}
pub trait Context<Req, ReqRes>: Copy + 'static {
unsafe fn new() -> Self;
fn req(self, req: Req) -> ReqRes;
}
#[allow(unions_with_drop_fields)]
pub union In<Cmd, ReqRes> {
cmd: Cmd,
req_res: ReqRes,
}
pub enum Out<Req, CmdRes> {
Req(Req),
CmdRes(CmdRes),
}
impl<Cmd, ReqRes> In<Cmd, ReqRes> {
pub unsafe fn into_cmd(self) -> Cmd {
self.cmd
}
pub unsafe fn into_req_res(self) -> ReqRes {
self.req_res
}
}