120 lines
2.8 KiB
Rust
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(),
|
|
}
|
|
}
|
|
}
|