use std::{error::Error, fmt};
use rama_macros::Extension;
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct Version(Http);
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Extension)]
#[extension(tags(http))]
pub struct TargetHttpVersion(pub Version);
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Extension)]
#[extension(tags(http))]
pub struct FallbackHttpVersion(pub Version);
#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Extension)]
#[extension(tags(http))]
pub struct HttpRequestVersion(pub Version);
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
enum Http {
Http09,
Http10,
Http11,
H2,
H3,
}
impl Version {
pub const HTTP_09: Self = Self(Http::Http09);
pub const HTTP_10: Self = Self(Http::Http10);
pub const HTTP_11: Self = Self(Http::Http11);
pub const HTTP_2: Self = Self(Http::H2);
pub const HTTP_3: Self = Self(Http::H3);
#[must_use]
pub const fn as_str(self) -> &'static str {
match self.0 {
Http::Http09 => "HTTP/0.9",
Http::Http10 => "HTTP/1.0",
Http::Http11 => "HTTP/1.1",
Http::H2 => "HTTP/2.0",
Http::H3 => "HTTP/3.0",
}
}
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
impl std::str::FromStr for Version {
type Err = InvalidVersion;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"HTTP/0.9" | "0.9" => Self::HTTP_09,
"HTTP/1.0" | "1.0" => Self::HTTP_10,
"HTTP/1.1" | "1.1" => Self::HTTP_11,
"HTTP/2" | "HTTP/2.0" | "2" | "2.0" => Self::HTTP_2,
"HTTP/3" | "HTTP/3.0" | "3" | "3.0" => Self::HTTP_3,
_ => return Err(InvalidVersion::new()),
})
}
}
impl Default for Version {
#[inline]
fn default() -> Self {
Self::HTTP_11
}
}
impl core::fmt::Debug for Version {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Default)]
#[non_exhaustive]
pub struct InvalidVersion;
impl InvalidVersion {
#[inline(always)]
pub fn new() -> Self {
Self
}
}
impl fmt::Display for InvalidVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("invalid HTTP version")
}
}
impl Error for InvalidVersion {}
use rama_utils::macros::serde_str::impl_serde_str;
impl_serde_str!(as_str Version);