sark-h2 0.29.2

Fiber-free HTTP/2 protocol primitives and manifold server for sark
use std::{convert::Infallible, ops};

use o3::buffer::{bytes::scope, hold::evidence::Off, storage::Shared};
use sark_core::{decode, request, request::frame::proof};
use sark_http::{
    field::metadata::section::rules,
    owner::handoff::{self, stage},
    request::body,
};

use crate::{
    conn::{self, event},
    server::response::{Detached, Handoff, Head, Pending, Receipt, head::Staged},
    stream,
};

#[doc(hidden)]
pub struct Prepared<
    'a,
    'req,
    'd,
    F: rules::Policy,
    E: event::Evidence = event::Retirement,
    S = Infallible,
    B = body::Retained<'req, 'd>,
> {
    pub(in crate::server::response) staged: Staged<'a, 'd, F, E>,
    pub(in crate::server::response) body: handoff::Plan<'req, 'd, S, B>,
}

impl<'a, 'req, 'd: 'req, F: rules::Policy, E: event::Evidence, B: stage::Body<'req, 'd>>
    Prepared<'a, 'req, 'd, F, E, Infallible, B>
{
    pub(crate) fn stream(&self) -> stream::Key {
        self.staged.stream
    }

    #[doc(hidden)]
    pub fn discard(self) {
        drop(self);
    }

    #[doc(hidden)]
    pub fn finish(self) -> Result<Option<Pending<'d>>, conn::Error> {
        let Self { staged, body } = self;
        let receipt = Off::resolve(body)?;
        staged.commit()?;
        Ok(receipt.into_pending())
    }

    pub(in crate::server) fn defer<M: Handoff>(
        self,
    ) -> Result<ops::ControlFlow<Head<'d>, Receipt<'d>>, conn::Error> {
        let Self { staged, body } = self;
        let receipt = M::resolve(body)?;
        staged.defer(receipt)
    }

    pub(in crate::server) fn detach<M: Handoff>(
        self,
    ) -> Result<Detached<'a, 'd, F, M, E, B::Deferred>, conn::Error>
    where
        B::Deferred: stage::Deferred<'d>,
    {
        let Self { staged, body } = self;
        let body = M::detach(body)?;
        Ok(Detached { staged, body })
    }
}

impl<'a, 'req, 'd: 'req, 'id, F: rules::Policy, E: event::Evidence, B: stage::Body<'req, 'd>>
    decode::Lineage<'id> for Prepared<'a, 'req, 'd, F, E, scope::Range<'id>, B>
{
    type Output = Prepared<'a, 'req, 'd, F, E, Infallible, B>;

    fn resolve_head<O: Into<scope::Owner<'id, Shared>>, P: proof::Proof>(
        self,
        head: request::Head<O, P>,
    ) -> Self::Output {
        let Self { staged, body } = self;
        Prepared {
            staged,
            body: body.resolve_head(head.into_owner()),
        }
    }
}