sark-core 0.2.1

the L7 layer for dope
Documentation
use http::{HeaderName, HeaderValue};

use crate::error::{Error, Result};
use crate::http::codec::Parse;

pub(super) type Trailers = Vec<(HeaderName, HeaderValue)>;

pub(super) struct Framing;

impl Framing {
    pub(super) fn parse_trailers(buf: &[u8]) -> Result<Option<(Trailers, usize)>> {
        if buf.len() >= 2 && buf[0] == b'\r' && buf[1] == b'\n' {
            return Ok(Some((Vec::new(), 2)));
        }

        let end = match Parse::find_double_crlf(buf) {
            Some(r) => r.end,
            None => return Ok(None),
        };

        let trailer_block = &buf[..end];
        let mut trailers = Vec::new();

        for line in trailer_block.split(|&b| b == b'\n') {
            let line = line.strip_suffix(b"\r").unwrap_or(line);
            if line.is_empty() {
                continue;
            }
            if let Some(colon) = line.iter().position(|&b| b == b':') {
                let name = &line[..colon];
                let value = &line[colon + 1..];
                let value = if value.first() == Some(&b' ') {
                    &value[1..]
                } else {
                    value
                };

                let name = HeaderName::from_bytes(name)
                    .map_err(|_| Error::BadRequest("Invalid trailer header name".into()))?;
                let value = HeaderValue::from_bytes(value)
                    .map_err(|_| Error::BadRequest("Invalid trailer header value".into()))?;
                trailers.push((name, value));
            }
        }

        Ok(Some((trailers, end)))
    }

    pub(super) fn find_crlf(buf: &[u8]) -> Option<usize> {
        if buf.len() < 2 {
            return None;
        }
        let mut i = 0;
        while i + 1 < buf.len() {
            if buf[i] == b'\r' && buf[i + 1] == b'\n' {
                return Some(i);
            }
            i += 1;
        }
        None
    }
}