sark-h2 0.24.0

Fiber-free HTTP/2 protocol primitives and manifold server for sark
Documentation
use std::pin;

use dope::{core::driver::route::Identity, manifold::network::listener::conn};
use o3::depot::queue::indexed::lanes::typed::Value;
use sark_core::{deadline, life, manifold::task::app::Runtime};
use sark_http::owner::cause;

use crate::{
    frame::numbers,
    server::task::{
        self, Borrowed, Target, registry,
        response::{Data, Response, deadline::Deadline},
        timers::Due,
    },
    stream,
};

pub(in crate::server::task) struct Expiry(deadline::Poll<Due>);

impl Expiry {
    pub(in crate::server::task) const fn new(due: deadline::Poll<Due>) -> Self {
        Self(due)
    }

    pub(in crate::server::task) fn apply<'d, ID: Identity + 'd, R, Q>(
        self,
        router: pin::Pin<&mut R>,
        tasks: &mut registry::Table<'d, ID, R::Task>,
        conn: conn::Id<'d, ID>,
        index: &mut registry::Index,
        state: &mut Borrowed<'_, 'd, R>,
        mode: &mut Q,
    ) -> Deadline
    where
        R: Runtime<'d, Target = Target<'d, ID>>,
        Q: life::Mode<conn::Id<'d, ID>, stream::Key>,
    {
        let due = match self.0 {
            deadline::Poll::Idle => return Deadline::Ready,
            deadline::Poll::Renewed => return Deadline::Wake,
            deadline::Poll::Expired(due) => due,
        };
        match due {
            Due::Exchange { key, phase } => {
                let xchg = task::identify(conn, key);
                let expiry = xchg.begin_expiry(mode, phase);
                if let Some(registry::Taken { task, .. }) = tasks.take_stream(index, conn, key) {
                    Runtime::cancel(router, task);
                    mode.observe(life::Event::TaskCancelled(xchg));
                }
                let (reply, done) = state.reset(xchg, numbers::ErrorCode::Cancel, mode.body(xchg));
                if let Some(write) = done {
                    task::release_retired(mode, conn, write, cause::Staging::Reset);
                }
                match reply {
                    Some(Value::Data(Data::Body { pending, .. })) => {
                        task::release_pending(mode, xchg, pending, cause::Staging::Reset)
                    }
                    Some(Value::Control(Response::Encoded(receipt))) => drop(receipt),
                    Some(Value::Control(
                        Response::Head { head, .. } | Response::DuplexHead { head, .. },
                    )) => head.discard(state.connection),
                    Some(Value::Data(Data::Duplex { .. }))
                    | Some(Value::Control(
                        Response::Status(_)
                        | Response::Sync(_)
                        | Response::Completion(_)
                        | Response::DuplexOpen { .. },
                    ))
                    | None => {}
                    Some(Value::Idle(never)) => match never {},
                }
                expiry.finish(mode);
                Deadline::Expired
            }
            Due::Wake { .. } => Deadline::Wake,
            Due::Critical | Due::Header { .. } => Deadline::Critical,
        }
    }
}