1use std::{error::Error, fmt};
8
9use rama_macros::Extension;
10
11#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
13pub struct Version(Http);
14
15#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Extension)]
16#[extension(tags(http))]
17pub struct TargetHttpVersion(pub Version);
23
24#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Extension)]
30#[extension(tags(http))]
31pub struct FallbackHttpVersion(pub Version);
32
33#[derive(Debug, Copy, Clone, Default, PartialEq, Eq, Extension)]
39#[extension(tags(http))]
40pub struct HttpRequestVersion(pub Version);
41
42#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)]
43enum Http {
44 Http09,
45 Http10,
46 Http11,
47 H2,
48 H3,
49}
50
51impl Version {
52 pub const HTTP_09: Self = Self(Http::Http09);
54
55 pub const HTTP_10: Self = Self(Http::Http10);
57
58 pub const HTTP_11: Self = Self(Http::Http11);
60
61 pub const HTTP_2: Self = Self(Http::H2);
63
64 pub const HTTP_3: Self = Self(Http::H3);
66
67 #[must_use]
69 pub const fn as_str(self) -> &'static str {
70 match self.0 {
71 Http::Http09 => "HTTP/0.9",
72 Http::Http10 => "HTTP/1.0",
73 Http::Http11 => "HTTP/1.1",
74 Http::H2 => "HTTP/2.0",
75 Http::H3 => "HTTP/3.0",
76 }
77 }
78}
79
80impl fmt::Display for Version {
81 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
82 f.write_str(self.as_str())
83 }
84}
85
86impl std::str::FromStr for Version {
87 type Err = InvalidVersion;
88
89 fn from_str(s: &str) -> Result<Self, Self::Err> {
92 Ok(match s {
93 "HTTP/0.9" | "0.9" => Self::HTTP_09,
94 "HTTP/1.0" | "1.0" => Self::HTTP_10,
95 "HTTP/1.1" | "1.1" => Self::HTTP_11,
96 "HTTP/2" | "HTTP/2.0" | "2" | "2.0" => Self::HTTP_2,
97 "HTTP/3" | "HTTP/3.0" | "3" | "3.0" => Self::HTTP_3,
98 _ => return Err(InvalidVersion::new()),
99 })
100 }
101}
102
103impl Default for Version {
104 #[inline]
105 fn default() -> Self {
106 Self::HTTP_11
107 }
108}
109
110impl core::fmt::Debug for Version {
111 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
112 f.write_str(self.as_str())
113 }
114}
115
116#[derive(Debug, Default)]
119#[non_exhaustive]
120pub struct InvalidVersion;
121
122impl InvalidVersion {
123 #[inline(always)]
124 pub fn new() -> Self {
125 Self
126 }
127}
128
129impl fmt::Display for InvalidVersion {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 f.write_str("invalid HTTP version")
132 }
133}
134
135impl Error for InvalidVersion {}
136
137use rama_utils::macros::serde_str::impl_serde_str;
138
139impl_serde_str!(as_str Version);
140
141