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> { $({ 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> { $({ 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], }