use std::{convert::Infallible, fmt, mem, pin};
use app::step;
use dope_core::driver;
use driver::{
retained,
schedule::{app, ready},
};
use o3::alloc;
use ready::task::owner;
use request::admit;
use sark_http::payload::owned;
use crate::{
decode,
decode::{dispatch, exec, request},
duplex,
manifold::task::{self, Target, response},
route,
};
#[derive(Debug)]
pub enum BindError<P = Infallible> {
Prepare(P),
Allocation(alloc::Error),
}
pub trait Bind<'d>: Sized
where
<Self::Runtime as decode::Decode>::Egress<'d>: 'd,
{
type Target: Target + 'd;
type Runtime: Runtime<'d, Target = Self::Target>;
type Error;
fn try_bind(self, bind: driver::Binding<'d>) -> Result<Self::Runtime, Self::Error>;
}
#[must_use]
#[repr(u8)]
pub enum Turn<'turn, 'd, C = ()> {
Idle,
Deferred,
Pending(step::Receipt<'turn, 'd>),
PendingReady(step::Receipt<'turn, 'd>),
Complete(C, step::Receipt<'turn, 'd>),
}
#[derive(Clone, Copy, Eq, PartialEq)]
pub enum Wake {
Ready,
Idle,
}
pub trait Handoff<'d, T: Target, C: response::Completion<'d>>: Sized {
type Complete;
fn pending(self, target: T);
fn complete<R, A, P>(self, target: T, output: response::Output<'d, R, A>) -> Self::Complete
where
R: route::Task<'d, A>,
P: response::Pack<'d, R, A, C>;
}
pub trait Runtime<'d>:
decode::Decode<Head: request::Head<Start: admit::Start<Self>>, Egress<'d>: 'd>
+ duplex::Application<'d>
+ Sized
{
type Task;
type Build: crate::body::Push<'d>;
type Target: Target + 'd;
type Completion: response::Completion<'d>;
type Admission;
type OwnerCause: fmt::Debug;
type RetireCause: fmt::Debug;
fn reject_step(error: <Self::Build as crate::body::Build<'d>>::StepError) -> route::Reject;
fn reject_push(error: <Self::Build as crate::body::Push<'d>>::Error) -> route::Reject;
fn rejection(error: &task::Error<Self::Admission>) -> route::Reject;
fn register(
self: pin::Pin<&Self>,
owner: owner::Owner<Self::Target>,
) -> Result<(), Self::OwnerCause>;
fn try_retire(
self: pin::Pin<&Self>,
owner: owner::Owner<Self::Target>,
) -> Result<(), Self::RetireCause>;
fn try_dispatch(
self: pin::Pin<&mut Self>,
req: request::Ready<exec::Task, Self::Prepared, owned::Segments<'d>>,
target: Self::Target,
owner: owner::Owner<Self::Target>,
parent: ready::Target<'d>,
) -> Result<Self::Task, task::Error<Self::Admission>>;
fn try_start(
&self,
req: Self::Prepared,
) -> Result<Self::Build, dispatch::Error<Infallible, Infallible, route::Reject>>;
fn try_built(
self: pin::Pin<&mut Self>,
output: <Self::Build as crate::body::Build<'d>>::Output,
target: Self::Target,
owner: owner::Owner<Self::Target>,
parent: ready::Target<'d>,
) -> Result<Self::Task, task::Error<Self::Admission>>;
fn drive<'turn, H: Handoff<'d, Self::Target, Self::Completion>>(
self: pin::Pin<&mut Self>,
scope: owner::Scope<Self::Target>,
work: app::Work<'turn, 'd>,
driver: &mut retained::Context<'_, '_, 'd>,
sink: H,
) -> Turn<'turn, 'd, H::Complete>;
fn has_work(self: pin::Pin<&Self>, scope: owner::Scope<Self::Target>) -> bool;
fn wake(self: pin::Pin<&mut Self>, scope: owner::Scope<Self::Target>);
fn try_wake(self: pin::Pin<&mut Self>, scope: owner::Scope<Self::Target>) -> Wake;
fn cancel(self: pin::Pin<&mut Self>, task: Self::Task);
}
const _: () = assert!(mem::size_of::<Turn<'static, 'static>>() == 1);