httplz 0.0.0

A sans-io, no-std HTTP implementation
Documentation
#[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 }),
		}
	}
}