sark-core 0.21.0

Fiber-free request, route, dispatch, and lifecycle core for Sark
Documentation
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),
}

/// Binds generated task storage to one driver domain.
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>;
}

/// Result of polling one generated multiplexed task.
#[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,
}

/// Linear monomorphized handoff into one protocol response adapter.
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>;
}

/// Allocation-free task execution selected independently of the protocol.
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;

    /// Exact unadmitted reason for one owner-lane registration.
    type OwnerCause: fmt::Debug;

    /// Exact reason one owner lane could not be retired.
    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;

    /// Binds the lane owner of one admitted session, classifying a lane this runtime
    /// does not own or a generation another registration already claimed.
    fn register(
        self: pin::Pin<&Self>,
        owner: owner::Owner<Self::Target>,
    ) -> Result<(), Self::OwnerCause>;

    /// Releases the lane owner of one closed session, classifying a foreign or stale
    /// lane and a generation whose tasks never retired.
    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);