sark-h2 0.28.3

Fiber-free HTTP/2 protocol primitives and manifold server for sark
use dope::{core::driver::route::Identity, manifold::network::listener::conn, net::wire};
use o3::mem::quota;
use sark_core::{
    decode::{self, request},
    manifold::{server::app as semantic, task::app::Runtime},
};
use sark_http::field::metadata::section::rules;

use crate::{
    conn::Error,
    server::{
        response::Handoff,
        runtime::app::Fault,
        state::Transitions,
        task::{
            Borrowed, Build, Target,
            app::{
                header::admit::Begin,
                turn::{Availability, Outcome, Turn, guard::Guard},
            },
            service, works,
        },
    },
};

pub(in crate::server::task::app) trait Schedule<'d, R>:
    works::Family + Begin<'d, R>
where
    R: Runtime<'d>,
{
    fn admit<ID: Identity + 'd, Q, W, A, P>(
        graph: &mut Self::Graph,
        turn: &mut Turn<'_, '_, '_, 'd, ID, R, Q, W, A, P>,
    ) -> quota::Admission<Result<Outcome, semantic::Error<Error, A::Failure>>>
    where
        R: Runtime<'d, Target = Target<'d, ID>>,
        Q: Transitions<conn::Id<'d, ID>>,
        Q::Retention: Handoff,
        W: wire::Spec,
        A: service::Select<R>
            + semantic::Application<'d, service::Connection<'d, A>, conn::Id<'d, ID>>,
        P: Fault<'d, W, A::Failure, ID, Build<A::Build>>;

    fn account(graph: &mut Self::Graph);

    fn has_pending<F: rules::Policy>(state: &mut Borrowed<'_, 'd, R, F>) -> Availability;

    fn has_local<F: rules::Policy>(state: &mut Borrowed<'_, 'd, R, F>) -> Availability {
        Self::has_pending(state)
    }

    fn is_ready<F: rules::Policy>(state: &mut Borrowed<'_, 'd, R, F>) -> Availability {
        match Self::has_local(state) {
            Availability::Ready => Availability::Ready,
            Availability::Idle if state.has_events() || state.responses.has_runnable() => {
                Availability::Ready
            }
            Availability::Idle => Availability::Idle,
        }
    }
}

impl<'d, R, U> Schedule<'d, R> for request::Plain<U>
where
    R: Runtime<'d>,
    R::Head: request::Head<Start = request::Plain<U>>,
    request::Plain<U>: Begin<'d, R>,
{
    fn admit<ID: Identity + 'd, Q, W, A, P>(
        graph: &mut Self::Graph,
        turn: &mut Turn<'_, '_, '_, 'd, ID, R, Q, W, A, P>,
    ) -> quota::Admission<Result<Outcome, semantic::Error<Error, A::Failure>>>
    where
        R: Runtime<'d, Target = Target<'d, ID>>,
        Q: Transitions<conn::Id<'d, ID>>,
        Q::Retention: Handoff,
        W: wire::Spec,
        A: service::Select<R>
            + semantic::Application<'d, service::Connection<'d, A>, conn::Id<'d, ID>>,
        P: Fault<'d, W, A::Failure, ID, Build<A::Build>>,
    {
        graph.admit(|source| match source {
            works::Plain::Build => turn.build(),
            works::Plain::Task => turn.task(),
            works::Plain::Ingress => turn.ingress(),
            works::Plain::Egress => {
                let pump = turn.pump();
                turn.egress(pump)
            }
        })
    }

    fn account(graph: &mut Self::Graph) {
        graph.account(works::Plain::Egress);
    }

    fn has_pending<F: rules::Policy>(state: &mut Borrowed<'_, 'd, R, F>) -> Availability {
        if state.build_ready.is_empty() {
            Availability::Idle
        } else {
            Availability::Ready
        }
    }
}

impl<'d, R, S> Schedule<'d, R> for S
where
    R: Runtime<'d> + decode::Guarded,
    R::Head: request::Head<Start = S>,
    S: Guard + works::Family<Graph = works::GuardedGraph> + Begin<'d, R>,
{
    fn admit<ID: Identity + 'd, Q, W, A, P>(
        graph: &mut Self::Graph,
        turn: &mut Turn<'_, '_, '_, 'd, ID, R, Q, W, A, P>,
    ) -> quota::Admission<Result<Outcome, semantic::Error<Error, A::Failure>>>
    where
        R: Runtime<'d, Target = Target<'d, ID>>,
        Q: Transitions<conn::Id<'d, ID>>,
        Q::Retention: Handoff,
        W: wire::Spec,
        A: service::Select<R>
            + semantic::Application<'d, service::Connection<'d, A>, conn::Id<'d, ID>>,
        P: Fault<'d, W, A::Failure, ID, Build<A::Build>>,
    {
        graph.admit(|source| match source {
            works::Guarded::Admission => turn.admission(),
            works::Guarded::Build => turn.build(),
            works::Guarded::Task => turn.task(),
            works::Guarded::Ingress => turn.ingress(),
            works::Guarded::Egress => {
                let pump = turn.guarded_pump();
                turn.egress(pump)
            }
        })
    }

    fn account(graph: &mut Self::Graph) {
        graph.account(works::Guarded::Egress);
    }

    fn has_pending<F: rules::Policy>(state: &mut Borrowed<'_, 'd, R, F>) -> Availability {
        if state.admission_ready.is_empty() && state.build_ready.is_empty() {
            Availability::Idle
        } else {
            Availability::Ready
        }
    }

    fn has_local<F: rules::Policy>(state: &mut Borrowed<'_, 'd, R, F>) -> Availability {
        if state.can_admit() || !state.build_ready.is_empty() {
            Availability::Ready
        } else {
            Availability::Idle
        }
    }
}