httplz/src/http.rs
2024-11-03 21:51:29 -05:00

103 lines
2.2 KiB
Rust

use crate::parse::{Line, Parse, ParseError};
use core::str::from_utf8;
pub const LINE_ENDING: &[u8] = b"\r\n";
macro_rules! versions {
($(($name:ident, $str:expr)),* $(,)?) => {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum Version<'a> {
$($name,)*
Unknown(&'a [u8]),
}
impl<'a> Parse<'a> for Version<'a> {
fn parse(data: &'a [u8]) -> Result<(usize, Self), Option<ParseError>> {
$({
const STR: &[u8] = $str.as_bytes();
let len = ((STR.len() <= data.len()) as usize) * STR.len();
let data = &data[..len];
if data.eq_ignore_ascii_case(STR) {
return Ok((STR.len(), Self::$name));
}
};)*
Ok((0, Self::Unknown(data)))
}
}
};
}
versions! {
(V1_0, "http/1.0"),
(V1_1, "http/1.1"),
}
macro_rules! methods {
($(($name:ident, $str:expr)),* $(,)?) => {
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum Method<'a> {
$($name,)*
Other(&'a str),
}
impl<'a> Parse<'a> for Method<'a> {
fn parse(data: &'a [u8]) -> Result<(usize, Self), Option<ParseError>> {
$({
const STR: &[u8] = $str.as_bytes();
let len = ((STR.len() <= data.len()) as usize) * STR.len();
let data = &data[..len];
if data.eq_ignore_ascii_case(STR) {
return Ok((STR.len(), Self::$name));
}
};)*
from_utf8(data).map(|s| (s.len(), Self::Other(s))).map_err(|_| Some(ParseError {
ctx: "method",
details: "unknown method was not a valid str",
}))
}
}
}
}
methods! {
(Get, "GET"),
(Head, "HEAD"),
(Options, "OPTIONS"),
(Trace, "TRACE"),
(Put, "PUT"),
(Delete, "DELETE"),
(Post, "POST"),
(Patch, "PATCH"),
(Connect, "CONNECT"),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct Status<'a> {
pub code: u16,
pub text: &'a str,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct RequestLine<'a> {
pub method: Method<'a>,
pub target: &'a str,
pub version: Version<'a>,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct StatusLine<'a> {
pub version: Version<'a>,
pub status: Status<'a>,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct Header<'a> {
pub name: &'a str,
pub value: &'a [u8],
}