sark-h2 0.29.3

Fiber-free HTTP/2 protocol primitives and manifold server for sark
use o3::buffer::{hold, resident, storage};
use sark_core::life::{self, exchange};
use sark_http::owner::evidence::Sink as _;
use sark_http::{
    owner::{evidence, handoff},
    payload::owned,
};

use crate::{
    conn,
    server::{response::Pending, state::Transitions},
    stream,
};

#[doc(hidden)]
pub struct Receipt<'d> {
    pending: Option<Pending<'d>>,
    linked: hold::Charge,
    copied: Option<evidence::Copy>,
}

impl<'d> Receipt<'d> {
    pub(super) fn from_ready(
        body: handoff::Ready<'d>,
        linked: hold::Charge,
    ) -> Result<Self, conn::Error> {
        let (pending, copied) = match body {
            handoff::Ready::Empty => (None, None),
            handoff::Ready::Owned(mut body) => {
                let body = storage::Shared::try_from(&mut body)
                    .map_err(storage::AllocError::Exhausted)
                    .map_err(owned::Error::Storage)
                    .map_err(conn::Error::Response)?;
                (Pending::single(resident::Shared::from(body)), None)
            }
            handoff::Ready::Copied(body) => {
                let (body, copy) = body.into_parts();
                (Pending::single(resident::Shared::from(body)), Some(copy))
            }
            handoff::Ready::Retained(body) => (Pending::single(resident::Shared::from(body)), None),
            handoff::Ready::Segmented(body) | handoff::Ready::Linked(body) => {
                (Pending::new(body), None)
            }
            handoff::Ready::Fixed(body) => {
                let body: resident::Shared<'d> = resident::Shared::from(body.as_slice());
                (Pending::single(body), None)
            }
        };
        Ok(Self::new(pending, linked, copied))
    }

    pub(super) const fn new(
        pending: Option<Pending<'d>>,
        linked: hold::Charge,
        copied: Option<evidence::Copy>,
    ) -> Self {
        Self {
            pending,
            linked,
            copied,
        }
    }

    pub(super) fn empty() -> Self {
        Self::new(None, hold::Charge::default(), None)
    }

    pub(in crate::server) fn into_pending(self) -> Option<Pending<'d>> {
        self.pending
    }

    pub(in crate::server) fn observe<C: Copy, M: Transitions<C>>(
        self,
        mode: &mut M,
        exchange: exchange::Id<C, stream::Key>,
    ) -> Option<Pending<'d>> {
        if let Some(copied) = self.copied {
            life::response::Sink::new(mode, exchange).copied(copied);
        }
        if M::ENABLED || M::EXCHANGE_DEADLINES {
            let charge = if M::ENABLED {
                self.pending
                    .as_ref()
                    .map_or(hold::Charge::default(), Pending::retention)
            } else {
                hold::Charge::default()
            };
            mode.observe(life::Event::ResponseCommitted {
                exchange,
                body_bytes: charge.logical_bytes,
                charge,
                linked: self.linked,
            });
        }
        self.pending
    }
}