trillium_http/headers/
unknown_header_name.rs1use super::{HeaderName, HeaderNameInner::UnknownHeader};
2use hashbrown::Equivalent;
3use smartcow::SmartCow;
4use std::{
5 fmt::{self, Debug, Display, Formatter},
6 hash::{Hash, Hasher},
7 ops::Deref,
8};
9
10#[derive(Clone)]
11pub(super) struct UnknownHeaderName<'a>(SmartCow<'a>);
12
13impl PartialEq for UnknownHeaderName<'_> {
14 fn eq(&self, other: &Self) -> bool {
15 self.0.eq_ignore_ascii_case(&other.0)
16 }
17}
18
19impl Eq for UnknownHeaderName<'_> {}
20
21impl Hash for UnknownHeaderName<'_> {
22 fn hash<H: Hasher>(&self, state: &mut H) {
23 for c in self.0.as_bytes() {
24 c.to_ascii_lowercase().hash(state);
25 }
26 }
27}
28
29impl Debug for UnknownHeaderName<'_> {
30 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
31 Debug::fmt(&self.0, f)
32 }
33}
34
35impl Display for UnknownHeaderName<'_> {
36 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
37 Display::fmt(&self.0, f)
38 }
39}
40
41impl<'a> From<UnknownHeaderName<'a>> for HeaderName<'a> {
42 fn from(value: UnknownHeaderName<'a>) -> Self {
43 HeaderName(UnknownHeader(value))
44 }
45}
46
47fn is_tchar(c: char) -> bool {
48 matches!(
49 c,
50 'a'..='z'
51 | 'A'..='Z'
52 | '0'..='9'
53 | '!'
54 | '#'
55 | '$'
56 | '%'
57 | '&'
58 | '\''
59 | '*'
60 | '+'
61 | '-'
62 | '.'
63 | '^'
64 | '_'
65 | '`'
66 | '|'
67 | '~'
68 )
69}
70
71impl UnknownHeaderName<'_> {
72 pub(crate) fn is_valid(&self) -> bool {
73 !self.is_empty() && self.0.chars().all(is_tchar)
76 }
77
78 pub(crate) fn into_owned(self) -> UnknownHeaderName<'static> {
79 UnknownHeaderName(self.0.into_owned())
80 }
81}
82
83impl From<String> for UnknownHeaderName<'static> {
84 fn from(value: String) -> Self {
85 Self(value.into())
86 }
87}
88
89impl<'a> From<&'a str> for UnknownHeaderName<'a> {
90 fn from(value: &'a str) -> Self {
91 Self(value.into())
92 }
93}
94
95impl<'a> From<SmartCow<'a>> for UnknownHeaderName<'a> {
96 fn from(value: SmartCow<'a>) -> Self {
97 Self(value)
98 }
99}
100
101impl<'a> From<UnknownHeaderName<'a>> for SmartCow<'a> {
102 fn from(value: UnknownHeaderName<'a>) -> Self {
103 value.0
104 }
105}
106
107impl Deref for UnknownHeaderName<'_> {
108 type Target = str;
109
110 fn deref(&self) -> &Self::Target {
111 &self.0
112 }
113}
114
115impl Equivalent<UnknownHeaderName<'_>> for &UnknownHeaderName<'_> {
116 fn equivalent(&self, key: &UnknownHeaderName<'_>) -> bool {
117 key.eq_ignore_ascii_case(self)
118 }
119}