sark-h2 0.28.0

Fiber-free HTTP/2 protocol primitives and manifold server for sark
use core::{marker, mem};

use sark_http::{
    field,
    field::metadata::{
        block, lower,
        section::{rules, state},
        strings,
    },
};
use state::decode::{Indexed, Session, Start};

use crate::{
    conn::ingress::header::sink::Header,
    hpack::decode::{self, sink},
};

pub(in crate::conn::ingress) struct Hpack<P: rules::Policy, A: rules::Push> {
    session: Session<P>,
    push: marker::PhantomData<fn() -> A>,
}

impl<P: rules::Policy, A: rules::Push> Hpack<P, A> {
    pub(super) fn new(session: Session<P>) -> Self {
        Self {
            session,
            push: marker::PhantomData,
        }
    }

    pub(in crate::conn::ingress) fn into_header(self) -> Header<P> {
        Header {
            session: self.session,
        }
    }

    fn failed(self, cause: lower::Error) -> (Self, decode::Failure<lower::Error>) {
        (self, decode::Failure::Sink(cause))
    }
}

impl<P: rules::Policy, A: rules::Push> sink::Direct for Hpack<P, A> {
    type Error = decode::Failure<lower::Error>;

    fn string(&mut self, cursor: &mut strings::Cursor, input: &[u8]) -> Result<(), Self::Error> {
        match self.session.string(*cursor, input) {
            lower::Step::Ready { cursor: next } => {
                *cursor = next;
                Ok(())
            }
            lower::Step::Bound { cause } => Err(decode::Error::from(cause).into()),
            lower::Step::Decode { cause, progress } => {
                Err(decode::Error::encoding(cause, progress).into())
            }
            lower::Step::Store { cause } => Err(decode::Failure::Sink(cause)),
        }
    }

    fn rollback(&mut self) {
        self.session.rollback();
    }
}

impl<P: rules::Policy, A: rules::Push> sink::Store for Hpack<P, A> {
    type Rule = ();
    type Completion = ();

    fn validate(&mut self, value: block::Validation) -> Result<(), Self::Error> {
        self.session.validate(value);
        Ok(())
    }

    fn begin(
        mut self,
        name: Option<block::Named<'_>>,
        indexing: field::Indexing,
    ) -> sink::Output<Self, sink::Begin<Self::Rule, Self::Completion>> {
        let start = match self.session.begin(name, indexing) {
            Ok(start) => start,
            Err(cause) => return Err(self.failed(cause)),
        };
        Ok((
            self,
            match start {
                Start::Skip => sink::Begin::Skip,
                Start::Buffered(rule) => sink::Begin::Buffered(rule),
                Start::Direct(done) | Start::Scratch(done) => sink::Begin::Direct(done),
            },
        ))
    }

    fn indexed(
        mut self,
        name: Option<block::Named<'_>>,
    ) -> sink::Output<Self, sink::Indexed<Self::Rule>> {
        let indexed = match self.session.indexed(name) {
            Ok(indexed) => indexed,
            Err(cause) => return Err(self.failed(cause)),
        };
        Ok((
            self,
            match indexed {
                Indexed::Skip => sink::Indexed::Skip,
                Indexed::Buffered(rule) => sink::Indexed::Buffered(rule),
            },
        ))
    }

    fn field(
        mut self,
        (): Self::Rule,
        value: block::Valued<'_>,
        indexing: field::Indexing,
        name: block::Named<'_>,
    ) -> Result<Self, (Self, Self::Error)> {
        match self.session.field::<A>(name, value, indexing) {
            Ok(()) => Ok(self),
            Err(cause) => Err(self.failed(cause)),
        }
    }

    fn direct(mut self, (): Self::Completion) -> Result<Self, (Self, Self::Error)> {
        match self.session.direct::<A>() {
            Ok(()) => Ok(self),
            Err(cause) => Err(self.failed(cause)),
        }
    }
}

const _: () =
    assert!(mem::size_of::<decode::Failure<lower::Error>>() == mem::size_of::<lower::Error>());