1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
use std::{ borrow::Cow, collections::HashMap, fmt, hash::{Hash, Hasher}, ops::Deref, }; #[derive(Clone, Eq)] pub struct HeaderName<'n>(Cow<'n, str>); impl<'n> HeaderName<'n> { pub fn new(header_name: impl Into<Cow<'n, str>>) -> HeaderName<'n> { HeaderName(header_name.into()) } } impl PartialEq for HeaderName<'_> { fn eq(&self, other: &Self) -> bool { self.as_ref().eq_ignore_ascii_case(other.as_ref()) } } impl AsRef<str> for HeaderName<'_> { fn as_ref(&self) -> &str { self.0.as_ref() } } impl Deref for HeaderName<'_> { type Target = str; fn deref(&self) -> &Self::Target { self.as_ref() } } impl<'n> Hash for HeaderName<'n> { fn hash<H: Hasher>(&self, state: &mut H) { self.as_ref().to_uppercase().hash(state) } } impl<'n> From<&'n str> for HeaderName<'n> { fn from(s: &'n str) -> Self { HeaderName(s.into()) } } impl From<String> for HeaderName<'_> { fn from(s: String) -> Self { HeaderName(s.into()) } } impl<'n> From<Cow<'n, str>> for HeaderName<'n> { fn from(s: Cow<'n, str>) -> Self { HeaderName(s) } } impl fmt::Debug for HeaderName<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_ref().fmt(f) } } impl fmt::Display for HeaderName<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.as_ref().fmt(f) } } pub type HeaderValue<'v> = Cow<'v, str>; pub type Headers<'h> = HashMap<HeaderName<'h>, HeaderValue<'h>>; #[cfg(test)] mod tests { use super::*; use std::{boxed::Box, error::Error, result::Result}; #[test] fn test_header_name() -> Result<(), Box<dyn Error>> { let mut headers = Headers::new(); headers.insert("Authorization".into(), "Test".into()); assert_eq!(headers.get(&"authorization".into()), Some(&"Test".into())); assert_eq!(headers.get(&"AUTHORIZATION".into()), Some(&"Test".into())); Ok(()) } }