sark-http 0.26.3

HTTP wire types, semantics, codecs, and ownership invariants for Sark
Documentation
use core::ops;

use o3::buffer::pool;
use state::range::Authority;

use crate::field::{
    head,
    metadata::{
        block,
        map::record,
        section::{rules, state},
    },
};

pub struct Raw {
    pub(super) core: state::Core,
}

pub struct Discard {
    pub(super) core: state::Core,
}

#[derive(Clone, Copy, PartialEq, Eq)]
#[doc(hidden)]
pub enum Omit {
    Authority,
    Discard(head::Name),
    Skip,
}

impl Raw {
    pub fn new(kind: rules::Kind) -> Self {
        Self {
            core: state::Core::new(kind, block::Connect::Disabled, block::Version::Two),
        }
    }

    pub fn finish(self) -> ((), block::Validation) {
        let status = self.core.control.finish().validation();
        ((), status)
    }

    pub fn finish_plan(self) -> ((), block::Validation, Option<block::Plan>) {
        let (plan, status) = self.core.control.finish().into_parts();
        ((), status, plan)
    }

    #[doc(hidden)]
    pub fn accept(&mut self, proof: block::Name) -> block::Validation {
        self.core.control.accept_name(proof.head())
    }

    #[doc(hidden)]
    pub fn retain<A: rules::Push>(
        &mut self,
        known: head::Name,
        field: record::View<'_>,
        retained: &[u8],
        scratch: &[u8],
    ) -> rules::Retention {
        self.core.check::<A>(known, field, retained, scratch)
    }

    #[doc(hidden)]
    pub fn store(&mut self, known: head::Name, range: ops::Range<usize>) {
        if known == head::Name::Authority && self.core.control.kind() == block::Kind::Request {
            match Authority::retained(range) {
                Some(saved) => self.core.authority = saved,
                None => self.core.control.reject(),
            }
        }
    }
}

impl Discard {
    pub fn finish(self) -> ((), block::Validation) {
        let status = self.core.control.finish().validation();
        ((), status)
    }

    pub fn finish_plan(self) -> ((), block::Validation, Option<block::Plan>) {
        let (plan, status) = self.core.control.finish().into_parts();
        ((), status, plan)
    }

    #[doc(hidden)]
    pub fn route(&self, proof: block::Name) -> Omit {
        let known = proof.head();
        if self.core.control.kind() == block::Kind::Request && known == head::Name::Authority {
            Omit::Authority
        } else if state::Core::is_checked(known) {
            Omit::Discard(known)
        } else {
            Omit::Skip
        }
    }

    #[doc(hidden)]
    pub fn accept(&mut self, proof: block::Name) -> block::Validation {
        self.core.control.accept_name(proof.head())
    }

    #[doc(hidden)]
    pub fn discard<A: rules::Push>(
        &mut self,
        known: head::Name,
        field: record::View<'_>,
        retained: &[u8],
        scratch: &[u8],
    ) {
        self.core.check::<A>(known, field, retained, scratch);
    }

    #[doc(hidden)]
    pub fn retain<A: rules::Push>(
        &mut self,
        known: head::Name,
        field: record::View<'_>,
        retained: &[u8],
        scratch: &[u8],
    ) -> rules::Retention {
        self.core.check::<A>(known, field, retained, scratch)
    }

    #[doc(hidden)]
    pub fn store(&mut self, range: ops::Range<usize>) {
        match Authority::retained(range) {
            Some(saved) => self.core.authority = saved,
            None => self.core.control.reject(),
        }
    }

    pub fn seal(&mut self, retained: &mut pool::Span) -> block::Validation {
        let (plan, check) = self.core.control.finish().into_parts();
        if check != block::Validation::Valid
            || plan.is_none_or(|plan| plan.form() != block::Form::Connect)
        {
            retained.truncate(0);
            self.core.authority = Authority::absent();
        }
        check
    }
}

const _: () = assert!(core::mem::size_of::<Raw>() == 24);
const _: () = assert!(core::mem::size_of::<Discard>() == 24);

impl rules::Validate for Raw {
    fn value(&mut self, check: block::Validation) {
        self.core.value(check);
    }
}

impl rules::Validate for Discard {
    fn value(&mut self, check: block::Validation) {
        self.core.value(check);
    }
}