Skip to main content

trillium_http/headers/
header_name.rs

1use super::{KnownHeaderName, UnknownHeaderName};
2use crate::Error;
3use HeaderNameInner::{KnownHeader, UnknownHeader};
4use std::{
5    fmt::{self, Debug, Display, Formatter},
6    hash::Hash,
7    str::FromStr,
8};
9
10/// The name of a http header. This can be either a
11/// [`KnownHeaderName`] or a string representation of an unknown
12/// header.
13#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
14pub struct HeaderName<'a>(pub(super) HeaderNameInner<'a>);
15
16impl Debug for HeaderName<'_> {
17    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
18        Debug::fmt(&self.0, f)
19    }
20}
21
22impl<'a> HeaderName<'a> {
23    pub(crate) fn parse(bytes: &'a [u8]) -> Result<Self, Error> {
24        std::str::from_utf8(bytes)
25            .map_err(|_| Error::InvalidHeaderName)
26            .map(HeaderName::from)
27    }
28}
29
30#[cfg(feature = "serde")]
31impl serde::Serialize for HeaderName<'_> {
32    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33    where
34        S: serde::Serializer,
35    {
36        serializer.serialize_str(self.as_ref())
37    }
38}
39
40#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
41pub(super) enum HeaderNameInner<'a> {
42    /// A `KnownHeaderName`
43    KnownHeader(KnownHeaderName),
44    UnknownHeader(UnknownHeaderName<'a>),
45}
46
47impl Debug for HeaderNameInner<'_> {
48    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
49        match self {
50            Self::KnownHeader(known) => Debug::fmt(known, f),
51            Self::UnknownHeader(unknown) => Debug::fmt(unknown, f),
52        }
53    }
54}
55
56impl<'a> HeaderName<'a> {
57    /// Convert a potentially-borrowed headername to a static
58    /// headername _by value_.
59    #[must_use]
60    pub fn into_owned(self) -> HeaderName<'static> {
61        HeaderName(match self.0 {
62            KnownHeader(known) => KnownHeader(known),
63            UnknownHeader(uhn) => UnknownHeader(uhn.into_owned()),
64        })
65    }
66
67    /// Turn a `&'b HeaderName<'a>` into a `HeaderName<'b>`
68    pub fn reborrow<'b: 'a>(&'b self) -> HeaderName<'b> {
69        match self.0 {
70            KnownHeader(khn) => khn.into(),
71            UnknownHeader(ref uhn) => uhn.reborrow().into(),
72        }
73    }
74
75    /// Convert a potentially-borrowed headername to a static
76    /// headername _by cloning if needed from a borrow_. If you have
77    /// ownership of a headername with a non-static lifetime, it is
78    /// preferable to use `into_owned`. This is the equivalent of
79    /// `self.clone().into_owned()`.
80    #[must_use]
81    pub fn to_owned(&self) -> HeaderName<'static> {
82        self.clone().into_owned()
83    }
84
85    /// Determine if this header name contains only valid token characters.
86    pub fn is_valid(&self) -> bool {
87        match &self.0 {
88            KnownHeader(_) => true,
89            UnknownHeader(uh) => uh.is_valid(),
90        }
91    }
92}
93
94impl PartialEq<KnownHeaderName> for HeaderName<'_> {
95    fn eq(&self, other: &KnownHeaderName) -> bool {
96        match &self.0 {
97            KnownHeader(k) => other == k,
98            UnknownHeader(_) => false,
99        }
100    }
101}
102
103impl PartialEq<KnownHeaderName> for &HeaderName<'_> {
104    fn eq(&self, other: &KnownHeaderName) -> bool {
105        match &self.0 {
106            KnownHeader(k) => other == k,
107            UnknownHeader(_) => false,
108        }
109    }
110}
111
112impl PartialEq<str> for HeaderName<'_> {
113    fn eq(&self, other: &str) -> bool {
114        self.as_ref() == other
115    }
116}
117
118impl PartialEq<&str> for HeaderName<'_> {
119    fn eq(&self, other: &&str) -> bool {
120        self.as_ref() == *other
121    }
122}
123
124impl From<String> for HeaderName<'static> {
125    fn from(s: String) -> Self {
126        Self(match s.parse::<KnownHeaderName>() {
127            Ok(khn) => KnownHeader(khn),
128            Err(()) => UnknownHeader(UnknownHeaderName::from(s)),
129        })
130    }
131}
132
133impl<'a> From<&'a str> for HeaderName<'a> {
134    fn from(s: &'a str) -> Self {
135        Self(match s.parse::<KnownHeaderName>() {
136            Ok(khn) => KnownHeader(khn),
137            Err(_e) => UnknownHeader(UnknownHeaderName::from(s)),
138        })
139    }
140}
141
142impl<'a> From<&'a HeaderName<'_>> for HeaderName<'a> {
143    fn from(value: &'a HeaderName<'_>) -> Self {
144        value.reborrow()
145    }
146}
147
148impl FromStr for HeaderName<'static> {
149    type Err = Error;
150
151    fn from_str(s: &str) -> Result<Self, Self::Err> {
152        if let Ok(known) = s.parse::<KnownHeaderName>() {
153            return Ok(known.into());
154        }
155        let uhn = UnknownHeaderName::from(s.to_string());
156        if uhn.is_valid() {
157            Ok(uhn.into())
158        } else {
159            Err(Error::InvalidHeaderName)
160        }
161    }
162}
163
164impl AsRef<str> for HeaderName<'_> {
165    fn as_ref(&self) -> &str {
166        match &self.0 {
167            KnownHeader(khn) => khn.as_ref(),
168            UnknownHeader(u) => u.as_ref(),
169        }
170    }
171}
172
173impl Display for HeaderName<'_> {
174    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
175        f.write_str(self.as_ref())
176    }
177}