h10 0.6.14

Simple HTTP/1.0 Server
Documentation
mod aditional;
pub mod builder;
mod common;
mod compat;
mod entity;
mod request;
mod response;

use std::fmt::{Debug, Display};

use builder::HeaderEntryBuilder;

pub use self::{
    aditional::{
        Accept, AcceptCharset, AcceptEncoding, AcceptLanguage, ContentLanguage, Link, MIMEVersion,
        RetryAfter, Title, URI,
    },
    common::{Date, Pragma},
    compat::Connection,
    entity::{Allow, ContentEncoding, ContentLength, ContentType, Expires, LastModified},
    request::{Authorization, From, IfModifiedSince, Referer, UserAgent},
    response::{Location, Server, WWWAuthenticate},
};

pub trait IntoHeader {
    fn into_header(self) -> HeaderEntry;
}

use std::{ops::Deref, rc::Rc, str::FromStr};

use crate::http::result::{H10LibError, H10LibResult};

#[derive(Debug, PartialEq, Eq)]
pub struct Headers(Vec<HeaderEntry>);
impl Headers {
    pub fn empty() -> Self {
        Self(vec![])
    }
    pub fn default_for_request() -> Self {
        let mut headers = Self::empty();

        headers.add(UserAgent::default().into_header());

        headers
    }
    pub fn add(&mut self, header_entry: HeaderEntry) {
        let mut maybe_idx: Option<usize> = None;
        for (idx, header) in self.0.iter().enumerate() {
            if header.name() == header_entry.name() {
                maybe_idx = Some(idx);
                break;
            } else {
                continue;
            }
        }

        if let Some(found_idx) = maybe_idx {
            self.0[found_idx] = header_entry;
        } else {
            self.0.push(header_entry);
        }
    }
    pub fn get(&self, header_name: &HeaderName) -> Option<&HeaderEntry> {
        let mut maybe_idx: Option<usize> = None;
        for (idx, header) in self.0.iter().enumerate() {
            if header.name() == header_name {
                maybe_idx = Some(idx);
                break;
            } else {
                continue;
            }
        }
        maybe_idx.and_then(|idx| self.0.get(idx))
    }

    pub fn parse(s: &str) -> H10LibResult<Self> {
        let headers_str = if s.len() > 0 {
            s
        } else {
            return Ok(Headers::empty());
        };

        let mut headers = vec![];

        let mut iter = headers_str.split("\r\n");

        let _discard_status_line = iter.next();

        while let Some(entry) = iter.next() {
            headers.push(entry.parse()?);
        }
        Ok(Self(headers))
    }
}

impl Deref for Headers {
    type Target = Vec<HeaderEntry>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}
#[derive(Debug, PartialEq, Eq)]
pub struct HeaderEntry {
    name: HeaderName,
    value: HeaderValue,
}

impl HeaderEntry {
    pub fn builder() -> HeaderEntryBuilder {
        HeaderEntryBuilder
    }

    pub fn into_inner(self) -> (HeaderName, HeaderValue) {
        let Self { name, value } = self;
        (name, value)
    }

    pub fn name(&self) -> &HeaderName {
        &self.name
    }

    pub fn value(&self) -> &HeaderValue {
        &self.value
    }
}

impl FromStr for HeaderEntry {
    type Err = H10LibError;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        if let Some((key, value)) = input.split_once(":") {
            Ok(Self {
                name: key.trim().parse()?,
                value: value.trim().parse()?,
            })
        } else {
            Err(H10LibError::HeadersParser(
                "Malformed HTTP Header entry".into(),
            ))
        }
    }
}

impl Display for HeaderEntry {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}: {}", self.name, self.value)
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct HeaderName(Rc<str>);

impl HeaderName {
    pub fn new_unchecked<S: AsRef<str>>(name: S) -> Self {
        let s = name.as_ref();
        Self(s.into())
    }
}

impl Deref for HeaderName {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl FromStr for HeaderName {
    type Err = H10LibError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self(s.into()))
    }
}

impl Display for HeaderName {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[derive(Debug, PartialEq, Eq)]
pub struct HeaderValue(Rc<str>);

impl HeaderValue {
    pub fn new_unchecked<S: AsRef<str>>(name: S) -> Self {
        let s = name.as_ref();
        Self(s.into())
    }
}

impl Deref for HeaderValue {
    type Target = str;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl FromStr for HeaderValue {
    type Err = H10LibError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Ok(Self(s.into()))
    }
}

impl Display for HeaderValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}