1#[derive(Clone, Copy, Debug, PartialEq)]
6pub enum HttpMethod {
7 GET,
10 POST,
13 PUT,
16 DELETE,
18 PATCH,
20 CONNECT,
22 OPTIONS,
24 TRACE,
26 HEAD,
29}
30
31#[derive(Debug, Clone, Copy, PartialEq)]
33pub struct InvalidHttpMethod;
34
35impl core::fmt::Display for InvalidHttpMethod {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37 write!(f, "Invalid HTTP method")
38 }
39}
40
41impl HttpMethod {
42 #[must_use]
43 pub fn as_str(self) -> &'static str {
45 match self {
46 HttpMethod::GET => "GET",
47 HttpMethod::POST => "POST",
48 HttpMethod::PUT => "PUT",
49 HttpMethod::DELETE => "DELETE",
50 HttpMethod::PATCH => "PATCH",
51 HttpMethod::CONNECT => "CONNECT",
52 HttpMethod::OPTIONS => "OPTIONS",
53 HttpMethod::TRACE => "TRACE",
54 HttpMethod::HEAD => "HEAD",
55 }
56 }
57}
58
59impl TryFrom<&str> for HttpMethod {
60 type Error = InvalidHttpMethod;
61
62 fn try_from(value: &str) -> Result<Self, Self::Error> {
63 match value {
64 "GET" => Ok(HttpMethod::GET),
65 "POST" => Ok(HttpMethod::POST),
66 "PUT" => Ok(HttpMethod::PUT),
67 "DELETE" => Ok(HttpMethod::DELETE),
68 "PATCH" => Ok(HttpMethod::PATCH),
69 "HEAD" => Ok(HttpMethod::HEAD),
70 "OPTIONS" => Ok(HttpMethod::OPTIONS),
71 "TRACE" => Ok(HttpMethod::TRACE),
72 "CONNECT" => Ok(HttpMethod::CONNECT),
73 _ => Err(InvalidHttpMethod),
74 }
75 }
76}
77
78impl TryFrom<&[u8]> for HttpMethod {
79 type Error = InvalidHttpMethod;
80
81 fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
82 match value {
83 b"GET" => Ok(HttpMethod::GET),
84 b"POST" => Ok(HttpMethod::POST),
85 b"PUT" => Ok(HttpMethod::PUT),
86 b"DELETE" => Ok(HttpMethod::DELETE),
87 b"PATCH" => Ok(HttpMethod::PATCH),
88 b"HEAD" => Ok(HttpMethod::HEAD),
89 b"OPTIONS" => Ok(HttpMethod::OPTIONS),
90 b"TRACE" => Ok(HttpMethod::TRACE),
91 b"CONNECT" => Ok(HttpMethod::CONNECT),
92 _ => Err(InvalidHttpMethod),
93 }
94 }
95}
96
97#[cfg(test)]
98mod tests {
99 use super::*;
100
101 #[test]
102 fn test_http_method_as_str() {
103 assert_eq!(HttpMethod::GET.as_str(), "GET");
104 assert_eq!(HttpMethod::POST.as_str(), "POST");
105 assert_eq!(HttpMethod::PUT.as_str(), "PUT");
106 assert_eq!(HttpMethod::DELETE.as_str(), "DELETE");
107 assert_eq!(HttpMethod::PATCH.as_str(), "PATCH");
108 assert_eq!(HttpMethod::CONNECT.as_str(), "CONNECT");
109 assert_eq!(HttpMethod::OPTIONS.as_str(), "OPTIONS");
110 assert_eq!(HttpMethod::TRACE.as_str(), "TRACE");
111 assert_eq!(HttpMethod::HEAD.as_str(), "HEAD");
112 }
113
114 #[test]
115 fn test_try_from_str() {
116 assert_eq!(HttpMethod::try_from("GET"), Ok(HttpMethod::GET));
118 assert_eq!(HttpMethod::try_from("POST"), Ok(HttpMethod::POST));
119 assert_eq!(HttpMethod::try_from("PUT"), Ok(HttpMethod::PUT));
120 assert_eq!(HttpMethod::try_from("DELETE"), Ok(HttpMethod::DELETE));
121 assert_eq!(HttpMethod::try_from("PATCH"), Ok(HttpMethod::PATCH));
122 assert_eq!(HttpMethod::try_from("HEAD"), Ok(HttpMethod::HEAD));
123 assert_eq!(HttpMethod::try_from("OPTIONS"), Ok(HttpMethod::OPTIONS));
124 assert_eq!(HttpMethod::try_from("TRACE"), Ok(HttpMethod::TRACE));
125 assert_eq!(HttpMethod::try_from("CONNECT"), Ok(HttpMethod::CONNECT));
126
127 assert_eq!(HttpMethod::try_from("get"), Err(InvalidHttpMethod));
129 assert_eq!(HttpMethod::try_from("INVALID"), Err(InvalidHttpMethod));
130 assert_eq!(HttpMethod::try_from(""), Err(InvalidHttpMethod));
131 assert_eq!(HttpMethod::try_from("123"), Err(InvalidHttpMethod));
132 }
133
134 #[test]
135 fn test_try_from_bytes() {
136 assert_eq!(HttpMethod::try_from(b"GET".as_slice()), Ok(HttpMethod::GET));
138 assert_eq!(
139 HttpMethod::try_from(b"POST".as_slice()),
140 Ok(HttpMethod::POST)
141 );
142 assert_eq!(HttpMethod::try_from(b"PUT".as_slice()), Ok(HttpMethod::PUT));
143 assert_eq!(
144 HttpMethod::try_from(b"DELETE".as_slice()),
145 Ok(HttpMethod::DELETE)
146 );
147 assert_eq!(
148 HttpMethod::try_from(b"PATCH".as_slice()),
149 Ok(HttpMethod::PATCH)
150 );
151 assert_eq!(
152 HttpMethod::try_from(b"HEAD".as_slice()),
153 Ok(HttpMethod::HEAD)
154 );
155 assert_eq!(
156 HttpMethod::try_from(b"OPTIONS".as_slice()),
157 Ok(HttpMethod::OPTIONS)
158 );
159 assert_eq!(
160 HttpMethod::try_from(b"TRACE".as_slice()),
161 Ok(HttpMethod::TRACE)
162 );
163 assert_eq!(
164 HttpMethod::try_from(b"CONNECT".as_slice()),
165 Ok(HttpMethod::CONNECT)
166 );
167
168 assert_eq!(
170 HttpMethod::try_from(b"get".as_slice()),
171 Err(InvalidHttpMethod)
172 );
173 assert_eq!(
174 HttpMethod::try_from(b"INVALID".as_slice()),
175 Err(InvalidHttpMethod)
176 );
177 assert_eq!(HttpMethod::try_from(b"".as_slice()), Err(InvalidHttpMethod));
178 assert_eq!(
179 HttpMethod::try_from(b"123".as_slice()),
180 Err(InvalidHttpMethod)
181 );
182 }
183
184 #[test]
185 fn test_invalid_http_method_display() {
186 let error = InvalidHttpMethod;
187 assert_eq!(format!("{error}"), "Invalid HTTP method");
188 }
189
190 #[test]
191 fn test_roundtrip_str_conversion() {
192 let methods = [
193 HttpMethod::GET,
194 HttpMethod::POST,
195 HttpMethod::PUT,
196 HttpMethod::DELETE,
197 HttpMethod::PATCH,
198 HttpMethod::HEAD,
199 HttpMethod::OPTIONS,
200 HttpMethod::TRACE,
201 HttpMethod::CONNECT,
202 ];
203
204 for method in &methods {
205 let str_repr = method.as_str();
206 let parsed = HttpMethod::try_from(str_repr).unwrap();
207 assert_eq!(*method, parsed);
208 }
209 }
210}