sark-http 0.22.0

HTTP wire types, semantics, codecs, and ownership invariants for Sark
Documentation
use o3::buffer::pool;

use crate::field::{
    head,
    metadata::{
        lower,
        map::record,
        section::{rules, state::fixed, storage},
    },
};

#[must_use = "push the validated authority field"]
pub struct Authority<'a, 'field> {
    append: pool::Append<'a, ([u8; storage::Tag::PREFIX_LEN], [&'field [u8]; 2]), pool::Span>,
    scratch: &'a storage::Scratch,
    state: &'a mut fixed::Discard,
    name: record::Span<'field>,
}

impl<'a, 'field> Authority<'a, 'field> {
    pub fn try_new(
        lease: &'a mut pool::Span,
        scratch: &'a storage::Scratch,
        state: &'a mut fixed::Discard,
        name: record::Span<'field>,
        value: record::Span<'field>,
        indexing: crate::field::Indexing,
    ) -> Result<Self, lower::Error> {
        let start = lease.len();
        let len = value.len();
        let prefix = storage::Tag::AUTHORITY
            .prefix_with(len, indexing)
            .ok_or(lower::Error::Prefix(storage::Tag::AUTHORITY, len))?;
        let value_at = start
            .checked_add(prefix.len())
            .ok_or(lower::Error::Layout([start, name.len(), len]))?;
        value_at
            .checked_add(len)
            .ok_or(lower::Error::Layout([start, name.len(), len]))?;
        let (first, second) = value.parts();
        let append = pool::Append::try_prefixed(lease, prefix, [first, second])
            .map_err(lower::Error::Write)?;
        Ok(Self {
            append,
            scratch,
            state,
            name,
        })
    }

    pub fn push<A: rules::Push>(self) {
        let Self {
            append,
            scratch,
            state,
            name,
        } = self;
        let (prefix, [first, second]) = append.input();
        let indexing =
            crate::field::Indexing::from_never(prefix[storage::Tag::PREFIX_LEN - 1] != 0);
        let field = record::View::new(name, record::Span::new(first, second)).with_index(indexing);
        let keep = state.retain::<A>(
            head::Name::Authority,
            field,
            append.as_slice(),
            scratch.authority(),
        );
        match keep {
            rules::Retention::Discard => {}
            rules::Retention::Retain => {
                let value_at = append.as_slice().len() + storage::Tag::PREFIX_LEN;
                let (lease, _) = append.commit();
                state.store(value_at..lease.len());
            }
        }
    }
}

const _: () = {
    assert!(
        size_of::<Authority<'static, 'static>>()
            == size_of::<record::View<'static>>() + 4 * size_of::<usize>()
    );
    assert!(
        size_of::<Option<Authority<'static, 'static>>>()
            == size_of::<Authority<'static, 'static>>()
    );
};