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)]
12pub struct HeaderValues(SmallVec<[HeaderValue; 1]>);
13impl Deref for HeaderValues {
14 type Target = [HeaderValue];
15
16 fn deref(&self) -> &Self::Target {
17 &self.0
18 }
19}
20
21#[cfg(feature = "serde")]
22impl serde::Serialize for HeaderValues {
23 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
24 where
25 S: serde::Serializer,
26 {
27 match &**self {
28 [one] => one.serialize(serializer),
29 several => several.serialize(serializer),
30 }
31 }
32}
33
34impl Default for HeaderValues {
35 fn default() -> Self {
36 Self(SmallVec::with_capacity(1))
37 }
38}
39
40impl DerefMut for HeaderValues {
41 fn deref_mut(&mut self) -> &mut Self::Target {
42 &mut self.0
43 }
44}
45
46impl Debug for HeaderValues {
47 fn fmt(&self, f: &mut Formatter<'_>) -> Result {
48 match self.one() {
49 Some(one) => Debug::fmt(one, f),
50 None => f.debug_list().entries(&self.0).finish(),
51 }
52 }
53}
54
55impl PartialEq<[&str]> for HeaderValues {
56 fn eq(&self, other: &[&str]) -> bool {
57 &**self == other
58 }
59}
60
61impl IntoIterator for HeaderValues {
62 type IntoIter = smallvec::IntoIter<[HeaderValue; 1]>;
63 type Item = HeaderValue;
64
65 fn into_iter(self) -> Self::IntoIter {
66 self.0.into_iter()
67 }
68}
69
70impl<'a> IntoIterator for &'a HeaderValues {
71 type IntoIter = std::slice::Iter<'a, HeaderValue>;
72 type Item = &'a HeaderValue;
73
74 fn into_iter(self) -> Self::IntoIter {
75 self.0.iter()
76 }
77}
78
79impl<I> FromIterator<I> for HeaderValues
80where
81 I: Into<HeaderValue>,
82{
83 fn from_iter<T: IntoIterator<Item = I>>(iter: T) -> Self {
84 Self(iter.into_iter().map(Into::into).collect())
85 }
86}
87
88impl HeaderValues {
89 #[must_use]
92 pub const fn new() -> Self {
93 Self(SmallVec::new_const())
94 }
95
96 pub const fn const_new(value: &'static str) -> Self {
98 Self(SmallVec::from_const([HeaderValue::const_new(value)]))
99 }
100
101 pub fn as_str(&self) -> Option<&str> {
104 self.one().and_then(HeaderValue::as_str)
105 }
106
107 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 {
130 ($($t:ty),*) => {
131 $(
132 impl From<$t> for HeaderValues {
133 fn from(value: $t) -> Self {
134 HeaderValue::from(value).into()
135 }
136 }
137 )*
138 };
139}
140
141delegate_from_to_header_value!(
142 &'static [u8],
143 Vec<u8>,
144 String,
145 usize,
146 u64,
147 u16,
148 u32,
149 i32,
150 i64,
151 Cow<'static, str>,
152 &'static str,
153 std::fmt::Arguments<'_>
154);
155
156impl From<HeaderValue> for HeaderValues {
157 fn from(v: HeaderValue) -> Self {
158 Self(smallvec![v])
159 }
160}
161
162impl<const N: usize, HV> From<[HV; N]> for HeaderValues
163where
164 HV: Into<HeaderValue>,
165{
166 fn from(v: [HV; N]) -> Self {
167 Self(v.into_iter().map(Into::into).collect())
168 }
169}
170
171impl<HV> From<Vec<HV>> for HeaderValues
172where
173 HV: Into<HeaderValue>,
174{
175 fn from(value: Vec<HV>) -> Self {
176 Self(value.into_iter().map(Into::into).collect())
177 }
178}
179
180impl<'a, HV> From<&'a [HV]> for HeaderValues
181where
182 &'a HV: Into<HeaderValue>,
183{
184 fn from(value: &'a [HV]) -> Self {
185 Self(value.iter().map(Into::into).collect())
186 }
187}
188
189impl PartialEq<str> for HeaderValues {
190 fn eq(&self, other: &str) -> bool {
191 self.as_str().is_some_and(|v| v == other)
192 }
193}
194
195impl PartialEq<&str> for HeaderValues {
196 fn eq(&self, other: &&str) -> bool {
197 self == *other
198 }
199}
200
201impl PartialEq<HeaderValue> for HeaderValues {
202 fn eq(&self, other: &HeaderValue) -> bool {
203 self.one().is_some_and(|inner| inner == other)
204 }
205}