trillium_http/headers/
header_values.rs

1use crate::HeaderValue;
2use smallvec::{smallvec, SmallVec};
3use smartcow::SmartCow;
4use std::{
5    borrow::Cow,
6    fmt::{Debug, Formatter, Result},
7    ops::{Deref, DerefMut},
8};
9
10/// A header value is a collection of one or more [`HeaderValue`]. It
11/// has been optimized for the "one [`HeaderValue`]" case, but can
12/// accomodate more than one value.
13#[derive(Clone, Eq, PartialEq)]
14pub struct HeaderValues(SmallVec<[HeaderValue; 1]>);
15impl Deref for HeaderValues {
16    type Target = [HeaderValue];
17
18    fn deref(&self) -> &Self::Target {
19        &self.0
20    }
21}
22
23#[cfg(feature = "serde")]
24impl serde::Serialize for HeaderValues {
25    fn serialize<S>(&self, serializer: S) -> std::prelude::v1::Result<S::Ok, S::Error>
26    where
27        S: serde::Serializer,
28    {
29        match self.one() {
30            Some(one) => one.serialize(serializer),
31            None => self.0.serialize(serializer),
32        }
33    }
34}
35
36impl Default for HeaderValues {
37    fn default() -> Self {
38        Self(SmallVec::with_capacity(1))
39    }
40}
41
42impl DerefMut for HeaderValues {
43    fn deref_mut(&mut self) -> &mut Self::Target {
44        &mut self.0
45    }
46}
47
48impl Debug for HeaderValues {
49    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
50        match self.one() {
51            Some(one) => Debug::fmt(one, f),
52            None => f.debug_list().entries(&self.0).finish(),
53        }
54    }
55}
56
57impl PartialEq<[&str]> for HeaderValues {
58    fn eq(&self, other: &[&str]) -> bool {
59        &**self == other
60    }
61}
62
63impl IntoIterator for HeaderValues {
64    type Item = HeaderValue;
65
66    type IntoIter = smallvec::IntoIter<[HeaderValue; 1]>;
67
68    fn into_iter(self) -> Self::IntoIter {
69        self.0.into_iter()
70    }
71}
72
73impl<'a> IntoIterator for &'a HeaderValues {
74    type Item = &'a HeaderValue;
75
76    type IntoIter = std::slice::Iter<'a, HeaderValue>;
77
78    fn into_iter(self) -> Self::IntoIter {
79        self.0.iter()
80    }
81}
82
83impl<I> FromIterator<I> for HeaderValues
84where
85    I: Into<HeaderValue>,
86{
87    fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
88        Self(iter.into_iter().map(Into::into).collect())
89    }
90}
91
92impl HeaderValues {
93    /// Builds an empty `HeaderValues`. This is not generally necessary
94    /// in application code. Using a `From` implementation is preferable.
95    #[must_use]
96    pub fn new() -> Self {
97        Self(SmallVec::with_capacity(1))
98    }
99
100    /// If there is only a single value, returns that header as a
101    /// borrowed string slice if it is utf8. If there are more than
102    /// one header value, or if the singular header value is not utf8,
103    /// `as_str` returns None.
104    pub fn as_str(&self) -> Option<&str> {
105        self.one().and_then(HeaderValue::as_str)
106    }
107
108    pub(crate) fn as_lower(&self) -> Option<SmartCow<'_>> {
109        self.one().and_then(HeaderValue::as_lower)
110    }
111
112    /// If there is only a single `HeaderValue` inside this
113    /// `HeaderValues`, `one` returns a reference to that value. If
114    /// there are more than one header value inside this
115    /// `HeaderValues`, `one` returns None.
116    pub fn one(&self) -> Option<&HeaderValue> {
117        if self.len() == 1 {
118            self.0.first()
119        } else {
120            None
121        }
122    }
123
124    /// Add another header value to this `HeaderValues`.
125    pub fn append(&mut self, value: impl Into<HeaderValue>) {
126        self.0.push(value.into());
127    }
128
129    /// Adds any number of other header values to this `HeaderValues`.
130    pub fn extend(&mut self, values: impl Into<HeaderValues>) {
131        let values = values.into();
132        self.0.extend(values);
133    }
134}
135
136// impl AsRef<[u8]> for HeaderValues {
137//     fn as_ref(&self) -> &[u8] {
138//         self.one().as_ref()
139//     }
140// }
141
142impl From<&'static [u8]> for HeaderValues {
143    fn from(value: &'static [u8]) -> Self {
144        HeaderValue::from(value).into()
145    }
146}
147
148impl From<Vec<u8>> for HeaderValues {
149    fn from(value: Vec<u8>) -> Self {
150        HeaderValue::from(value).into()
151    }
152}
153
154impl From<String> for HeaderValues {
155    fn from(value: String) -> Self {
156        HeaderValue::from(value).into()
157    }
158}
159
160impl From<&'static str> for HeaderValues {
161    fn from(value: &'static str) -> Self {
162        HeaderValue::from(value).into()
163    }
164}
165
166impl From<Cow<'static, str>> for HeaderValues {
167    fn from(value: Cow<'static, str>) -> Self {
168        HeaderValue::from(value).into()
169    }
170}
171
172impl From<HeaderValue> for HeaderValues {
173    fn from(v: HeaderValue) -> Self {
174        Self(smallvec![v])
175    }
176}
177
178impl<HV> From<Vec<HV>> for HeaderValues
179where
180    HV: Into<HeaderValue>,
181{
182    fn from(v: Vec<HV>) -> Self {
183        Self(v.into_iter().map(Into::into).collect())
184    }
185}