From 5dc2a6b2fc66b69d109a582d0c575dc9d4e9b67d Mon Sep 17 00:00:00 2001 From: Hugo Osvaldo Barrera Date: Mon, 27 Mar 2023 19:14:10 +0200 Subject: [PATCH] Add Method::from_static Allows creating constant `Method` instances, e.g.: const PROPFIND: Method = Method::from_static(b"PROPFIND"); Fixes: https://github.com/hyperium/http/issues/587 --- src/method.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/src/method.rs b/src/method.rs index b7b3b357..519696fa 100644 --- a/src/method.rs +++ b/src/method.rs @@ -136,6 +136,31 @@ impl Method { } } + /// Convert static bytes into a `Method`. + /// + /// The method name can only be up to 15 bytes long. Any remaining bytes are ignored. + /// + /// # Panics + /// + /// If the input bytes are not a valid method name. + pub const fn from_static(src: &'static [u8]) -> Method { + match src { + b"OPTIONS" => Method::OPTIONS, + b"GET" => Method::GET, + b"POST" => Method::POST, + b"PUT" => Method::PUT, + b"DELETE" => Method::DELETE, + b"HEAD" => Method::HEAD, + b"TRACE" => Method::TRACE, + b"CONNECT" => Method::CONNECT, + b"PATCH" => Method::PATCH, + _ => { + let inline = InlineExtension::from_static(src); + Method(ExtensionInline(inline)) + } + } + } + fn extension_inline(src: &[u8]) -> Result { let inline = InlineExtension::new(src)?; @@ -335,6 +360,29 @@ mod extension { Ok(InlineExtension(data, src.len() as u8)) } + /// Convert static bytes into an `InlineExtension`. + /// + /// Only the first 15 characters are used. Any remaining bytes are ignored. + /// + /// # Panics + /// + /// If the input bytes are not a valid method name. + pub const fn from_static(src: &'static [u8]) -> InlineExtension { + let mut i = 0; + let mut dst = [0u8;15]; + while i < src.len() { + let byte = src[i] ; + let v = METHOD_CHARS[byte as usize]; + if v == 0 { + panic!("Invalid byte for method name."); + } + dst[i] = byte; + i += 1; + } + + InlineExtension(dst, src.len() as u8) + } + pub fn as_str(&self) -> &str { let InlineExtension(ref data, len) = self; // Safety: the invariant of InlineExtension ensures that the first @@ -440,6 +488,18 @@ mod test { assert_eq!(Method::GET, &Method::GET); } + #[test] + fn test_from_static() { + assert_eq!(Method::from_static(b"PROPFIND"), Method::from_bytes(b"PROPFIND").unwrap()); + assert_eq!(Method::from_static(b"GET"), Method::from_bytes(b"GET").unwrap()); + } + + #[test] + #[should_panic] + fn test_from_static_bad() { + Method::from_static(b"\0"); + } + #[test] fn test_invalid_method() { assert!(Method::from_str("").is_err());