#[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 struct RequestLine<'a> { pub method: &'a str, 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, } /// Headers that impact the state of the connection #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum HeaderSpecial { TransferEncodingChunked, ContentLength(usize), } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct HeaderOther<'a> { pub name: &'a str, pub value: &'a [u8], } impl<'a, Name, Value> From<(&'a Name, &'a Value)> for HeaderOther<'a> where Name: AsRef + ?Sized, Value: AsRef<[u8]> + ?Sized, { fn from(value: (&'a Name, &'a Value)) -> Self { let (name, value) = value; let name = name.as_ref(); let value = value.as_ref(); Self { name, value } } } #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub enum Header<'a> { Special(HeaderSpecial), Other(HeaderOther<'a>), } impl<'a> From for Header<'a> { fn from(value: HeaderSpecial) -> Self { Self::Special(value) } } impl<'a> From> for Header<'a> { fn from(value: HeaderOther<'a>) -> Self { Self::Other(value) } } impl<'a, Name, Value> From<(&'a Name, &'a Value)> for Header<'a> where Name: AsRef + ?Sized, Value: AsRef<[u8]> + ?Sized, { fn from(value: (&'a Name, &'a Value)) -> Self { let (name, value) = value; let name = name.as_ref(); let value = value.as_ref(); match () { _ if name.eq_ignore_ascii_case("transfer-encoding") && value.eq_ignore_ascii_case(b"chunked") => { Header::Special(HeaderSpecial::TransferEncodingChunked) }, _ if name.eq_ignore_ascii_case("content-length") => { match core::str::from_utf8(value) .ok() .and_then(|s| s.parse().ok()) { Some(v) => Header::Special(HeaderSpecial::ContentLength(v)), _ => Header::Other(HeaderOther { name, value }), } }, _ => Header::Other(HeaderOther { name, value }), } } }