sark 0.12.0

Simple Asynchronous Rust webKit - Server
Documentation
#![allow(clippy::too_many_arguments)]

use std::ops::Range;

use sark_core::error::Result;
use sark_core::http::codec::BodyFraming;
use sark_core::http::head::Flags;

use super::plan::HeaderValue;
use super::spec::RouteParams;
use crate::dispatch::BodySource;
use crate::request;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum BodyPolicy {
    Buffered,
    Discarded,
}

mod body_mode {
    use super::BodyPolicy;
    use crate::dispatch::BodySource;

    pub trait Sealed {
        const POLICY: BodyPolicy;

        fn bytes<B: BodySource>(body: &mut B) -> &[u8];
    }

    pub enum Buffered {}

    impl Sealed for Buffered {
        const POLICY: BodyPolicy = BodyPolicy::Buffered;

        fn bytes<B: BodySource>(body: &mut B) -> &[u8] {
            body.contiguous()
        }
    }

    pub enum Discarded {}

    impl Sealed for Discarded {
        const POLICY: BodyPolicy = BodyPolicy::Discarded;

        fn bytes<B: BodySource>(_body: &mut B) -> &[u8] {
            &[]
        }
    }
}

pub trait BodyMode: body_mode::Sealed {
    const POLICY: BodyPolicy = <Self as body_mode::Sealed>::POLICY;

    fn bytes<B: BodySource>(body: &mut B) -> &[u8] {
        <Self as body_mode::Sealed>::bytes(body)
    }
}

impl BodyMode for body_mode::Buffered {}
impl BodyMode for body_mode::Discarded {}

pub use body_mode::{Buffered, Discarded};

pub enum HeaderParse<H> {
    NeedMore,
    Bad,
    Ready {
        headers: H,
        head_len: usize,
        body_framing: BodyFraming,
        flags: Flags,
        accept_gzip: bool,
    },
}

pub trait RouteRequestImpl {
    type HeaderSlot: Copy;
    type RawHeaders: Default;
    type RawParams: Default;
    type Params<'req>: RouteParams<'req, Raw = Self::RawParams>;
    type Headers<'req>;
    type ParsedBody<'req>;
    type BodyMode: BodyMode;

    const FULL: bool = false;
    const BODY_POLICY: BodyPolicy = <Self::BodyMode as BodyMode>::POLICY;

    fn parse_body<'req>(raw: &'req [u8]) -> Result<Self::ParsedBody<'req>>;

    fn header_slot_bytes(_name: &[u8]) -> Option<Self::HeaderSlot> {
        None
    }

    fn parse_headers<const PARSE_ACCEPT_ENCODING: bool>(
        req_bytes: &[u8],
        headers_start: usize,
        max_header_count: usize,
    ) -> HeaderParse<Self::RawHeaders>;

    fn set_header_raw<V: HeaderValue>(
        _headers: &mut Self::RawHeaders,
        _slot: Self::HeaderSlot,
        _value: &V,
    ) -> Result<()> {
        Ok(())
    }

    fn set_query_name_raw<V: HeaderValue>(
        _headers: &mut Self::RawHeaders,
        _name: &[u8],
        _value: &V,
    ) -> Result<()> {
        Ok(())
    }

    fn set_query_slice_raw(
        _headers: &mut Self::RawHeaders,
        _name: &[u8],
        _input: &[u8],
        _range: Range<usize>,
    ) -> Result<()> {
        Ok(())
    }

    fn parse_query_raw(
        _headers: &mut Self::RawHeaders,
        _input: &[u8],
        _range: Range<usize>,
    ) -> Result<()> {
        Ok(())
    }

    fn build_headers<'req>(
        req: &request::Ref<'req>,
        headers: Self::RawHeaders,
    ) -> Result<Self::Headers<'req>>;

    fn build_params<'req>(
        req: &request::Ref<'req>,
        params: Self::RawParams,
    ) -> Option<Self::Params<'req>>
    where
        Self::Params<'req>: RouteParams<'req>,
    {
        <Self::Params<'req> as RouteParams<'req>>::from_raw(req, params)
    }
}