#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum Version { HTTP1_1, } impl core::fmt::Display for Version { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { match self { Version::HTTP1_1 => write!(f, "HTTP/1.1"), } } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum Method<'a> { Get, Head, Options, Trace, Put, Delete, Post, Patch, Connect, Other(&'a str), } impl<'a> Method<'a> { pub fn new_from_str(s: &'a str) -> Self { match s { _ if s.eq_ignore_ascii_case("get") => Method::Get, _ if s.eq_ignore_ascii_case("head") => Method::Head, _ if s.eq_ignore_ascii_case("options") => Method::Options, _ if s.eq_ignore_ascii_case("trace") => Method::Trace, _ if s.eq_ignore_ascii_case("put") => Method::Put, _ if s.eq_ignore_ascii_case("delete") => Method::Delete, _ if s.eq_ignore_ascii_case("post") => Method::Post, _ if s.eq_ignore_ascii_case("patch") => Method::Patch, _ if s.eq_ignore_ascii_case("connect") => Method::Connect, s => Method::Other(s), } } } impl core::fmt::Display for Method<'_> { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { use Method::*; let s = match self { Get => "GET", Head => "HEAD", Options => "OPTIONS", Trace => "TRACE", Put => "PUT", Delete => "DELETE", Post => "POST", Patch => "PATCH", Connect => "CONNECT", Other(s) => s, }; write!(f, "{s}") } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct RequestLine<'a> { pub method: Method<'a>, pub target: &'a str, pub version: Version, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct StatusLine<'a> { pub version: Version, pub status_code: u16, pub status_text: &'a str, } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Header<'a> { pub name: &'a str, pub value: &'a [u8], } impl Header<'_> { pub fn special(&self) -> Option { let Self { name, value } = self; match () { _ if name.eq_ignore_ascii_case("transfer-encoding") && value.eq_ignore_ascii_case(b"chunked") => { Some(HeaderSpecial::TransferEncodingChunked) }, _ if name.eq_ignore_ascii_case("content-length") => core::str::from_utf8(value) .ok() .and_then(|s| s.parse().ok()) .map(HeaderSpecial::ContentLength), _ => None, } } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum HeaderSpecial { TransferEncodingChunked, ContentLength(usize), } impl<'a, Name, Value> From<(&'a Name, &'a Value)> for Header<'a> where Name: AsRef + ?Sized, Value: AsRef<[u8]> + ?Sized, { fn from((name, value): (&'a Name, &'a Value)) -> Self { Header { name: name.as_ref(), value: value.as_ref(), } } }