sark-h2 0.22.0

Fiber-free HTTP/2 protocol primitives and manifold server for sark
Documentation
use dope::core::driver::schedule::app;
use o3::buffer::resident;
use sark_core::{
    decode::{self, request, state},
    manifold::{
        schedule,
        server::{
            Connection as _, Event,
            drain::{self, Events, Progress},
        },
    },
};
use sark_http::field::metadata::section::rules;

use crate::{
    conn::{event, machine},
    server::{
        self,
        state::exchange::Accepted,
        sync::{Book, book::ingress},
    },
};

type Connection<'d, R> = machine::Connection<
    crate::ServerRole,
    <R as decode::Decode>::Plan,
    resident::Shared<'d>,
    rules::RejectPush,
    event::Ignore,
>;
type Incoming<'d, R> = Event<Connection<'d, R>>;

/// Executes the selected synchronous request family on its connection.
pub trait Dispatch<'d, S = <<Self as decode::Decode>::Head as request::Head>::Start>:
    decode::Decode<Prepared: request::Synchronous, Egress<'d>: 'd> + Sized
{
    fn ingress(
        &self,
        book: &mut Book<'d, Self>,
        conn: &mut Connection<'d, Self>,
        limits: server::Config,
        next: impl FnMut(&mut Connection<'d, Self>) -> Option<Incoming<'d, Self>>,
    );

    fn events(
        &self,
        book: &mut Book<'d, Self>,
        conn: &mut Connection<'d, Self>,
        limits: server::Config,
    ) {
        self.ingress(book, conn, limits, |conn| {
            conn.ready().map(drain::Ready::take)
        });
        self.pump::<false, _>(book, conn, limits, schedule::Egress::Unchanged, || Some(()));
    }

    fn drive(
        &self,
        book: &mut Book<'d, Self>,
        conn: &mut Connection<'d, Self>,
        limits: server::Config,
        work: app::Work<'_, '_>,
    ) -> Progress {
        let drain = Events::fair(work, |mut drain| {
            self.ingress(book, conn, limits, |conn| drain.next(conn));
            drain.finish()
        });
        self.pump::<true, _>(book, conn, limits, schedule::Egress::Unchanged, || {
            work.permit()
        });
        if conn.ingress().is_blocked() && book.has_ready() {
            self.pump::<false, _>(book, conn, limits, schedule::Egress::Unchanged, || {
                work.permit()
            });
        }
        drain
    }

    fn pump<const ROUND: bool, P>(
        &self,
        book: &mut Book<'d, Self>,
        conn: &mut Connection<'d, Self>,
        limits: server::Config,
        egress: schedule::Egress,
        permit: impl FnMut() -> Option<P>,
    ) -> schedule::Report;
    fn clear(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>);
}

impl<'d, R, U> Dispatch<'d, request::Plain<U>> for R
where
    R: decode::Decode<Egress<'d>: 'd>,
    R::Head: request::Head<Start = request::Plain<U>>,
    R::Prepared: request::Synchronous,
    U: state::Flow<R::Prepared, state::Routed, Family = R::Routes> + state::Admission<
            R::Prepared,
            state::Routed,
            Accepted<'d>,
            Output = <<R::Prepared as request::Prepared>::Family as state::Family<R::Prepared>>::State<Accepted<'d>>,
        >,
{
    fn ingress(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>, limits: server::Config,
        next: impl FnMut(&mut Connection<'d, Self>) -> Option<Incoming<'d, Self>>) {
        ingress::Ingress::new(book, conn).run(self, limits, next);
    }

    fn pump<const ROUND: bool, P>(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>, limits: server::Config, egress: schedule::Egress, permit: impl FnMut() -> Option<P>) -> schedule::Report {
        book.pump::<ROUND, _, _>(conn, self, limits, egress, permit)
    }

    fn clear(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>) {
        book.clear(conn);
    }
}

impl<'d, R, G> Dispatch<'d, request::Guarded<G>> for R
where
    R: decode::Guarded<Egress<'d>: 'd>,
    R::Head: request::Head<Start = request::Guarded<G>>,
    R::Prepared: request::Synchronous,
    R::Routes: state::Family<R::Prepared, State<state::Routed> = G>,
    G: state::Flow<R::Prepared, state::Routed, Family = R::Routes>,
{
    fn ingress(
        &self,
        book: &mut Book<'d, Self>,
        conn: &mut Connection<'d, Self>,
        limits: server::Config,
        next: impl FnMut(&mut Connection<'d, Self>) -> Option<Incoming<'d, Self>>,
    ) {
        ingress::Ingress::new(book, conn).run(self, limits, next);
    }

    fn pump<const ROUND: bool, P>(
        &self,
        book: &mut Book<'d, Self>,
        conn: &mut Connection<'d, Self>,
        limits: server::Config,
        egress: schedule::Egress,
        permit: impl FnMut() -> Option<P>,
    ) -> schedule::Report {
        book.pump::<ROUND, _, _>(conn, self, limits, egress, permit)
    }

    fn clear(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>) {
        book.clear(conn);
    }
}

impl<'d, R, U, G> Dispatch<'d, request::Start<U, G>> for R
where
    R: decode::Guarded<Egress<'d>: 'd>,
    R::Head: request::Head<Start = request::Start<U, G>>,
    R::Prepared: request::Synchronous,
    R::Routes: state::Family<R::Prepared, State<state::Routed> = G>,
    U: state::Admission<
            R::Prepared,
            state::Routed,
            Accepted<'d>,
            Output = <<R::Prepared as request::Prepared>::Family as state::Family<R::Prepared>>::State<Accepted<'d>>,
        >,
    G: state::Flow<R::Prepared, state::Routed, Family = R::Routes>,
{
    fn ingress(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>, limits: server::Config,
        next: impl FnMut(&mut Connection<'d, Self>) -> Option<Incoming<'d, Self>>) {
        ingress::Ingress::new(book, conn).run(self, limits, next);
    }

    fn pump<const ROUND: bool, P>(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>, limits: server::Config, egress: schedule::Egress, permit: impl FnMut() -> Option<P>) -> schedule::Report {
        book.pump::<ROUND, _, _>(conn, self, limits, egress, permit)
    }

    fn clear(&self, book: &mut Book<'d, Self>, conn: &mut Connection<'d, Self>) {
        book.clear(conn);
    }
}