trillium_http/headers/
header_values.rs1use crate::HeaderValue;
2use smallvec::{SmallVec, smallvec};
3use std::{
4 borrow::Cow,
5 fmt::{Debug, Formatter, Result},
6 ops::{Deref, DerefMut},
7};
8
9#[derive(Clone, Eq, PartialEq)]
13pub struct HeaderValues(SmallVec<[HeaderValue; 1]>);
14impl Deref for HeaderValues {
15 type Target = [HeaderValue];
16
17 fn deref(&self) -> &Self::Target {
18 &self.0
19 }
20}
21
22#[cfg(feature = "serde")]
23impl serde::Serialize for HeaderValues {
24 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
25 where
26 S: serde::Serializer,
27 {
28 match &**self {
29 [one] => one.serialize(serializer),
30 several => several.serialize(serializer),
31 }
32 }
33}
34
35impl Default for HeaderValues {
36 fn default() -> Self {
37 Self(SmallVec::with_capacity(1))
38 }
39}
40
41impl DerefMut for HeaderValues {
42 fn deref_mut(&mut self) -> &mut Self::Target {
43 &mut self.0
44 }
45}
46
47impl Debug for HeaderValues {
48 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
49 match self.one() {
50 Some(one) => Debug::fmt(one, f),
51 None => f.debug_list().entries(&self.0).finish(),
52 }
53 }
54}
55
56impl PartialEq<[&str]> for HeaderValues {
57 fn eq(&self, other: &[&str]) -> bool {
58 &**self == other
59 }
60}
61
62impl IntoIterator for HeaderValues {
63 type IntoIter = smallvec::IntoIter<[HeaderValue; 1]>;
64 type Item = HeaderValue;
65
66 fn into_iter(self) -> Self::IntoIter {
67 self.0.into_iter()
68 }
69}
70
71impl<'a> IntoIterator for &'a HeaderValues {
72 type IntoIter = std::slice::Iter<'a, HeaderValue>;
73 type Item = &'a HeaderValue;
74
75 fn into_iter(self) -> Self::IntoIter {
76 self.0.iter()
77 }
78}
79
80impl<I> FromIterator<I> for HeaderValues
81where
82 I: Into<HeaderValue>,
83{
84 fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
85 Self(iter.into_iter().map(Into::into).collect())
86 }
87}
88
89impl HeaderValues {
90 #[must_use]
93 pub const fn new() -> Self {
94 Self(SmallVec::new_const())
95 }
96
97 pub const fn const_new(value: &'static str) -> Self {
99 Self(SmallVec::from_const([HeaderValue::const_new(value)]))
100 }
101
102 pub fn as_str(&self) -> Option<&str> {
107 self.one().and_then(HeaderValue::as_str)
108 }
109
110 pub fn one(&self) -> Option<&HeaderValue> {
115 if self.len() == 1 {
116 self.0.first()
117 } else {
118 None
119 }
120 }
121
122 pub fn append(&mut self, value: impl Into<HeaderValue>) {
124 self.0.push(value.into());
125 }
126
127 pub fn extend(&mut self, values: impl Into<HeaderValues>) {
129 let values = values.into();
130 self.0.extend(values);
131 }
132}
133
134macro_rules! delegate_from_to_header_value {
141 ($($t:ty),*) => {
142 $(
143 impl From<$t> for HeaderValues {
144 fn from(value: $t) -> Self {
145 HeaderValue::from(value).into()
146 }
147 }
148 )*
149 };
150}
151
152delegate_from_to_header_value!(
153 &'static [u8],
154 Vec<u8>,
155 String,
156 usize,
157 u64,
158 u16,
159 u32,
160 i32,
161 i64,
162 Cow<'static, str>,
163 &'static str,
164 std::fmt::Arguments<'_>
165);
166
167impl From<HeaderValue> for HeaderValues {
168 fn from(v: HeaderValue) -> Self {
169 Self(smallvec![v])
170 }
171}
172
173impl<const N: usize, HV> From<[HV; N]> for HeaderValues
174where
175 HV: Into<HeaderValue>,
176{
177 fn from(v: [HV; N]) -> Self {
178 Self(v.into_iter().map(Into::into).collect())
179 }
180}
181
182impl<HV> From<Vec<HV>> for HeaderValues
183where
184 HV: Into<HeaderValue>,
185{
186 fn from(value: Vec<HV>) -> Self {
187 Self(value.into_iter().map(Into::into).collect())
188 }
189}
190
191impl<'a, HV> From<&'a [HV]> for HeaderValues
192where
193 &'a HV: Into<HeaderValue>,
194{
195 fn from(value: &'a [HV]) -> Self {
196 Self(value.iter().map(Into::into).collect())
197 }
198}
199
200impl PartialEq<str> for HeaderValues {
201 fn eq(&self, other: &str) -> bool {
202 self.as_str().is_some_and(|v| v == other)
203 }
204}
205
206impl PartialEq<&str> for HeaderValues {
207 fn eq(&self, other: &&str) -> bool {
208 self == *other
209 }
210}
211
212impl PartialEq<HeaderValue> for HeaderValues {
213 fn eq(&self, other: &HeaderValue) -> bool {
214 self.one().is_some_and(|inner| inner == other)
215 }
216}