Browse Source

optimize Method

Ondřej Hruška 3 months ago
parent
commit
2827c9bbe5
Signed by: Ondřej Hruška <ondra@ondrovo.com> GPG key ID: 2C5FD5035250423D
4 changed files with 72 additions and 47 deletions
  1. 2 2
      CHANGELOG.md
  2. 2 0
      README.md
  3. 67 44
      src/enums.rs
  4. 1 1
      src/lib.rs

+ 2 - 2
CHANGELOG.md View File

@@ -1,9 +1,9 @@
1 1
 # 0.3.0
2 2
 
3 3
 - Added lifetime parameter to `HttpMethod`
4
-- Changed `HttpMethod::OTHER(&'static str)` to `HttpMethod::OTHER(Cow<'a, str>)`
4
+- Changed `HttpMethod` to `HttpMethod<'a>(Cow<'a, str>)`
5 5
 - Added unit tests
6
-- Converted one Into impl to From
6
+- Added support for the `http` crate's `Method` struct (optional feature)
7 7
 
8 8
 # 0.2.4
9 9
 

+ 2 - 0
README.md View File

@@ -2,3 +2,5 @@ Rust implementation of Digest Auth hashing algorithms,
2 2
 as defined in IETF RFC 2069, 2617, and 7616.
3 3
 
4 4
 This crate provides the authentication header parsing and generation code.
5
+
6
+Please see the docs and tests for examples.

+ 67 - 44
src/enums.rs View File

@@ -170,11 +170,19 @@ impl Display for Charset {
170 170
 
171 171
 /// HTTP method (used when generating the response hash for some Qop options)
172 172
 #[derive(Debug, PartialEq, Clone)]
173
-pub enum HttpMethod<'a> {
174
-    GET,
175
-    POST,
176
-    HEAD,
177
-    OTHER(Cow<'a, str>),
173
+pub struct HttpMethod<'a>(pub Cow<'a, str>);
174
+
175
+// Well-known methods are provided as convenient associated constants
176
+impl<'a> HttpMethod<'a> {
177
+    pub const GET : Self = HttpMethod(Cow::Borrowed("GET"));
178
+    pub const POST : Self = HttpMethod(Cow::Borrowed("POST"));
179
+    pub const PUT : Self = HttpMethod(Cow::Borrowed("PUT"));
180
+    pub const DELETE : Self = HttpMethod(Cow::Borrowed("DELETE"));
181
+    pub const HEAD : Self = HttpMethod(Cow::Borrowed("HEAD"));
182
+    pub const OPTIONS : Self = HttpMethod(Cow::Borrowed("OPTIONS"));
183
+    pub const CONNECT : Self = HttpMethod(Cow::Borrowed("CONNECT"));
184
+    pub const PATCH : Self = HttpMethod(Cow::Borrowed("PATCH"));
185
+    pub const TRACE : Self = HttpMethod(Cow::Borrowed("TRACE"));
178 186
 }
179 187
 
180 188
 impl<'a> Default for HttpMethod<'a> {
@@ -186,66 +194,61 @@ impl<'a> Default for HttpMethod<'a> {
186 194
 impl<'a> Display for HttpMethod<'a> {
187 195
     /// Convert to uppercase string
188 196
     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
189
-        f.write_str(match self {
190
-            HttpMethod::GET => "GET",
191
-            HttpMethod::POST => "POST",
192
-            HttpMethod::HEAD => "HEAD",
193
-            HttpMethod::OTHER(s) => s,
194
-        })
197
+        f.write_str(&self.0)
195 198
     }
196 199
 }
197 200
 
198 201
 impl<'a> From<&'a str> for HttpMethod<'a> {
199 202
     fn from(s: &'a str) -> Self {
200
-        match s {
201
-            "GET" => HttpMethod::GET,
202
-            "POST" => HttpMethod::POST,
203
-            "HEAD" => HttpMethod::HEAD,
204
-            s => HttpMethod::OTHER(Cow::Borrowed(s)),
205
-        }
203
+        Self(s.into())
206 204
     }
207 205
 }
208 206
 
209 207
 impl<'a> From<&'a [u8]> for HttpMethod<'a> {
210 208
     fn from(s: &'a [u8]) -> Self {
211
-        String::from_utf8_lossy(s).into()
209
+        Self(String::from_utf8_lossy(s).into())
212 210
     }
213 211
 }
214 212
 
215 213
 impl<'a> From<String> for HttpMethod<'a> {
216 214
     fn from(s: String) -> Self {
217
-        match &s[..] {
218
-            "GET" => HttpMethod::GET,
219
-            "POST" => HttpMethod::POST,
220
-            "HEAD" => HttpMethod::HEAD,
221
-            _ => HttpMethod::OTHER(Cow::Owned(s)),
222
-        }
215
+        Self(s.into())
223 216
     }
224 217
 }
225 218
 
226 219
 impl<'a> From<Cow<'a, str>> for HttpMethod<'a> {
227 220
     fn from(s: Cow<'a, str>) -> Self {
228
-        match &s[..] {
229
-            "GET" => HttpMethod::GET,
230
-            "POST" => HttpMethod::POST,
231
-            "HEAD" => HttpMethod::HEAD,
232
-            _ => HttpMethod::OTHER(s),
233
-        }
221
+        Self(s)
234 222
     }
235 223
 }
236 224
 
237 225
 #[cfg(feature = "http")]
238 226
 impl From<http::Method> for HttpMethod<'static> {
239 227
     fn from(method: http::Method) -> Self {
240
-        match method {
241
-            http::Method::GET => HttpMethod::GET,
242
-            http::Method::POST => HttpMethod::POST,
243
-            http::Method::HEAD => HttpMethod::HEAD,
244
-            other => HttpMethod::OTHER(other.to_string().into()),
228
+        match method.as_str() {
229
+            // Avoid cloning when possible
230
+            "GET" => Self::GET,
231
+            "POST" => Self::POST,
232
+            "PUT" => Self::PUT,
233
+            "DELETE" => Self::DELETE,
234
+            "HEAD" => Self::HEAD,
235
+            "OPTIONS" => Self::OPTIONS,
236
+            "CONNECT" => Self::CONNECT,
237
+            "PATCH" => Self::PATCH,
238
+            "TRACE" => Self::TRACE,
239
+            // Clone custom strings. This is inefficient, but the inner string is private
240
+            other => Self(other.to_owned().into())
245 241
         }
246 242
     }
247 243
 }
248 244
 
245
+#[cfg(feature = "http")]
246
+impl<'a> From<&'a http::Method> for HttpMethod<'a> {
247
+    fn from(method: &'a http::Method) -> HttpMethod<'a> {
248
+        Self(method.as_str().into())
249
+    }
250
+}
251
+
249 252
 #[cfg(test)]
250 253
 mod test {
251 254
     use crate::error::Error::{BadCharset, BadQop, UnknownAlgorithm};
@@ -373,55 +376,75 @@ mod test {
373 376
         // Well known 'static
374 377
         assert_eq!(HttpMethod::GET, "GET".into());
375 378
         assert_eq!(HttpMethod::POST, "POST".into());
379
+        assert_eq!(HttpMethod::PUT, "PUT".into());
380
+        assert_eq!(HttpMethod::DELETE, "DELETE".into());
376 381
         assert_eq!(HttpMethod::HEAD, "HEAD".into());
382
+        assert_eq!(HttpMethod::OPTIONS, "OPTIONS".into());
383
+        assert_eq!(HttpMethod::CONNECT, "CONNECT".into());
384
+        assert_eq!(HttpMethod::PATCH, "PATCH".into());
385
+        assert_eq!(HttpMethod::TRACE, "TRACE".into());
377 386
         // As bytes
378 387
         assert_eq!(HttpMethod::GET, "GET".as_bytes().into());
379 388
         assert_eq!(
380
-            HttpMethod::OTHER(Cow::Borrowed("ěščř")),
389
+            HttpMethod(Cow::Borrowed("ěščř")),
381 390
             "ěščř".as_bytes().into()
382 391
         );
383 392
         assert_eq!(
384
-            HttpMethod::OTHER(Cow::Owned("AB�".to_string())),
393
+            HttpMethod(Cow::Owned("AB�".to_string())), // Lossy conversion
385 394
             (&[65u8, 66, 156][..]).into()
386 395
         );
387 396
         // Well known String
388 397
         assert_eq!(HttpMethod::GET, String::from("GET").into());
389 398
         // Custom String
390 399
         assert_eq!(
391
-            HttpMethod::OTHER(Cow::Borrowed("NonsenseMethod")),
400
+            HttpMethod(Cow::Borrowed("NonsenseMethod")),
392 401
             "NonsenseMethod".into()
393 402
         );
394 403
         assert_eq!(
395
-            HttpMethod::OTHER(Cow::Owned("NonsenseMethod".to_string())),
404
+            HttpMethod(Cow::Owned("NonsenseMethod".to_string())),
396 405
             "NonsenseMethod".to_string().into()
397 406
         );
398 407
         // Custom Cow
399 408
         assert_eq!(HttpMethod::HEAD, Cow::Borrowed("HEAD").into());
400 409
         assert_eq!(
401
-            HttpMethod::OTHER(Cow::Borrowed("NonsenseMethod")),
410
+            HttpMethod(Cow::Borrowed("NonsenseMethod")),
402 411
             Cow::Borrowed("NonsenseMethod").into()
403 412
         );
404 413
         // to string
405 414
         assert_eq!("GET".to_string(), HttpMethod::GET.to_string());
406 415
         assert_eq!("POST".to_string(), HttpMethod::POST.to_string());
416
+        assert_eq!("PUT".to_string(), HttpMethod::PUT.to_string());
417
+        assert_eq!("DELETE".to_string(), HttpMethod::DELETE.to_string());
407 418
         assert_eq!("HEAD".to_string(), HttpMethod::HEAD.to_string());
419
+        assert_eq!("OPTIONS".to_string(), HttpMethod::OPTIONS.to_string());
420
+        assert_eq!("CONNECT".to_string(), HttpMethod::CONNECT.to_string());
421
+        assert_eq!("PATCH".to_string(), HttpMethod::PATCH.to_string());
422
+        assert_eq!("TRACE".to_string(), HttpMethod::TRACE.to_string());
423
+
408 424
         assert_eq!(
409 425
             "NonsenseMethod".to_string(),
410
-            HttpMethod::OTHER(Cow::Borrowed("NonsenseMethod")).to_string()
426
+            HttpMethod(Cow::Borrowed("NonsenseMethod")).to_string()
411 427
         );
412 428
         assert_eq!(
413 429
             "NonsenseMethod".to_string(),
414
-            HttpMethod::OTHER(Cow::Owned("NonsenseMethod".to_string())).to_string()
430
+            HttpMethod(Cow::Owned("NonsenseMethod".to_string())).to_string()
415 431
         );
416 432
     }
417 433
 
418 434
     #[cfg(feature = "http")]
419 435
     #[test]
420 436
     fn test_http_crate() {
421
-        assert_eq!(HttpMethod::GET, http::Method::GET.into());
437
+        assert_eq!(HttpMethod::GET, http::Method::GET.clone().into());
422 438
         assert_eq!(
423
-            HttpMethod::OTHER(Cow::Owned("BANANA".to_string())),
439
+            HttpMethod(Cow::Owned("BANANA".to_string())),
424 440
             http::Method::from_str("BANANA").unwrap().into()
425 441
         );
442
+
443
+        assert_eq!(HttpMethod::GET, (&http::Method::GET).into());
444
+        let x = http::Method::from_str("BANANA").unwrap();
445
+        assert_eq!(
446
+            HttpMethod(Cow::Borrowed("BANANA")),
447
+            (&x).into()
448
+        );
426 449
     }
427 450
 }

+ 1 - 1
src/lib.rs View File

@@ -83,7 +83,7 @@ mod test {
83 83
         let mut prompt = crate::parse(src).unwrap();
84 84
         let answer = prompt.respond(&context).unwrap();
85 85
 
86
-        let str = answer.to_string().replace(", ", ",\n  ");
86
+        let str = answer.to_string().replace(", ", ",\n  "); // This is only for easier reading
87 87
 
88 88
         assert_eq!(
89 89
             str,