httplz/src/parts.rs

101 lines
2.4 KiB
Rust

#[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<str> + ?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<HeaderSpecial> for Header<'a> {
fn from(value: HeaderSpecial) -> Self {
Self::Special(value)
}
}
impl<'a> From<HeaderOther<'a>> 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<str> + ?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 }),
}
}
}