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 fn new() -> Self {
94 Self(SmallVec::with_capacity(1))
95 }
96
97 pub fn as_str(&self) -> Option<&str> {
102 self.one().and_then(HeaderValue::as_str)
103 }
104
105 pub fn one(&self) -> Option<&HeaderValue> {
110 if self.len() == 1 {
111 self.0.first()
112 } else {
113 None
114 }
115 }
116
117 pub fn append(&mut self, value: impl Into<HeaderValue>) {
119 self.0.push(value.into());
120 }
121
122 pub fn extend(&mut self, values: impl Into<HeaderValues>) {
124 let values = values.into();
125 self.0.extend(values);
126 }
127}
128
129macro_rules! delegate_from_to_header_value {
136 ($($t:ty),*) => {
137 $(
138 impl From<$t> for HeaderValues {
139 fn from(value: $t) -> Self {
140 HeaderValue::from(value).into()
141 }
142 }
143 )*
144 };
145}
146
147delegate_from_to_header_value!(
148 &'static [u8],
149 Vec<u8>,
150 String,
151 usize,
152 u64,
153 u16,
154 u32,
155 i32,
156 i64,
157 Cow<'static, str>,
158 &'static str,
159 std::fmt::Arguments<'_>
160);
161
162impl From<HeaderValue> for HeaderValues {
163 fn from(v: HeaderValue) -> Self {
164 Self(smallvec![v])
165 }
166}
167
168impl<const N: usize, HV> From<[HV; N]> for HeaderValues
169where
170 HV: Into<HeaderValue>,
171{
172 fn from(v: [HV; N]) -> Self {
173 Self(v.into_iter().map(Into::into).collect())
174 }
175}
176
177impl<HV> From<Vec<HV>> for HeaderValues
178where
179 HV: Into<HeaderValue>,
180{
181 fn from(value: Vec<HV>) -> Self {
182 Self(value.into_iter().map(Into::into).collect())
183 }
184}
185
186impl<'a, HV> From<&'a [HV]> for HeaderValues
187where
188 &'a HV: Into<HeaderValue>,
189{
190 fn from(value: &'a [HV]) -> Self {
191 Self(value.iter().map(Into::into).collect())
192 }
193}
194
195impl PartialEq<str> for HeaderValues {
196 fn eq(&self, other: &str) -> bool {
197 self.as_str().is_some_and(|v| v == other)
198 }
199}
200
201impl PartialEq<&str> for HeaderValues {
202 fn eq(&self, other: &&str) -> bool {
203 self == *other
204 }
205}
206
207impl PartialEq<HeaderValue> for HeaderValues {
208 fn eq(&self, other: &HeaderValue) -> bool {
209 self.one().is_some_and(|inner| inner == other)
210 }
211}