1 use bitflags::bitflags; 2 use http::Method; 3 use std::{ 4 fmt, 5 fmt::{Debug, Formatter}, 6 }; 7 8 bitflags! { 9 /// A filter that matches one or more HTTP methods. 10 pub struct MethodFilter: u16 { 11 /// Match `DELETE` requests. 12 const DELETE = 0b000000010; 13 /// Match `GET` requests. 14 const GET = 0b000000100; 15 /// Match `HEAD` requests. 16 const HEAD = 0b000001000; 17 /// Match `OPTIONS` requests. 18 const OPTIONS = 0b000010000; 19 /// Match `PATCH` requests. 20 const PATCH = 0b000100000; 21 /// Match `POST` requests. 22 const POST = 0b001000000; 23 /// Match `PUT` requests. 24 const PUT = 0b010000000; 25 /// Match `TRACE` requests. 26 const TRACE = 0b100000000; 27 } 28 } 29 30 /// Error type used when converting a [`Method`] to a [`MethodFilter`] fails. 31 #[derive(Debug)] 32 pub struct NoMatchingMethodFilter { 33 method: Method, 34 } 35 36 impl NoMatchingMethodFilter { 37 /// Get the [`Method`] that couldn't be converted to a [`MethodFilter`]. method(&self) -> &Method38 pub fn method(&self) -> &Method { 39 &self.method 40 } 41 } 42 43 impl fmt::Display for NoMatchingMethodFilter { fmt(&self, f: &mut Formatter<'_>) -> fmt::Result44 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { 45 write!(f, "no `MethodFilter` for `{}`", self.method.as_str()) 46 } 47 } 48 49 impl std::error::Error for NoMatchingMethodFilter {} 50 51 impl TryFrom<Method> for MethodFilter { 52 type Error = NoMatchingMethodFilter; 53 try_from(m: Method) -> Result<Self, NoMatchingMethodFilter>54 fn try_from(m: Method) -> Result<Self, NoMatchingMethodFilter> { 55 match m { 56 Method::DELETE => Ok(MethodFilter::DELETE), 57 Method::GET => Ok(MethodFilter::GET), 58 Method::HEAD => Ok(MethodFilter::HEAD), 59 Method::OPTIONS => Ok(MethodFilter::OPTIONS), 60 Method::PATCH => Ok(MethodFilter::PATCH), 61 Method::POST => Ok(MethodFilter::POST), 62 Method::PUT => Ok(MethodFilter::PUT), 63 Method::TRACE => Ok(MethodFilter::TRACE), 64 other => Err(NoMatchingMethodFilter { method: other }), 65 } 66 } 67 } 68 69 #[cfg(test)] 70 mod tests { 71 use super::*; 72 73 #[test] from_http_method()74 fn from_http_method() { 75 assert_eq!( 76 MethodFilter::try_from(Method::DELETE).unwrap(), 77 MethodFilter::DELETE 78 ); 79 80 assert_eq!( 81 MethodFilter::try_from(Method::GET).unwrap(), 82 MethodFilter::GET 83 ); 84 85 assert_eq!( 86 MethodFilter::try_from(Method::HEAD).unwrap(), 87 MethodFilter::HEAD 88 ); 89 90 assert_eq!( 91 MethodFilter::try_from(Method::OPTIONS).unwrap(), 92 MethodFilter::OPTIONS 93 ); 94 95 assert_eq!( 96 MethodFilter::try_from(Method::PATCH).unwrap(), 97 MethodFilter::PATCH 98 ); 99 100 assert_eq!( 101 MethodFilter::try_from(Method::POST).unwrap(), 102 MethodFilter::POST 103 ); 104 105 assert_eq!( 106 MethodFilter::try_from(Method::PUT).unwrap(), 107 MethodFilter::PUT 108 ); 109 110 assert_eq!( 111 MethodFilter::try_from(Method::TRACE).unwrap(), 112 MethodFilter::TRACE 113 ); 114 115 assert!(MethodFilter::try_from(http::Method::CONNECT) 116 .unwrap_err() 117 .to_string() 118 .contains("CONNECT")); 119 } 120 } 121