httplz/src/parts.rs
2024-10-24 15:27:11 -04:00

120 lines
2.8 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 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<HeaderSpecial> {
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<str> + ?Sized,
Value: AsRef<[u8]> + ?Sized,
{
fn from((name, value): (&'a Name, &'a Value)) -> Self {
Header {
name: name.as_ref(),
value: value.as_ref(),
}
}
}