1mod entry;
3mod header_name;
4mod header_value;
5mod header_values;
6mod known_header_name;
7mod unknown_header_name;
8
9#[cfg(feature = "unstable")]
10pub mod qpack;
11
12#[cfg(not(feature = "unstable"))]
13pub(crate) mod qpack;
14
15use crate::headers::entry::{OccupiedEntryInner, VacantEntryInner};
16pub use entry::{Entry, OccupiedEntry, VacantEntry};
17use hashbrown::{
18 HashMap,
19 hash_map::{self, Entry as HashbrownEntry},
20};
21pub use header_name::HeaderName;
22use header_name::HeaderNameInner;
23pub use header_value::HeaderValue;
24pub use header_values::HeaderValues;
25pub use known_header_name::KnownHeaderName;
26use std::{
27 collections::{
28 BTreeMap,
29 btree_map::{self, Entry as BTreeEntry},
30 },
31 fmt::{self, Debug, Display, Formatter},
32};
33use unknown_header_name::UnknownHeaderName;
34
35#[derive(Debug, Clone, PartialEq, Eq, Default)]
37#[must_use]
38pub struct Headers {
39 known: BTreeMap<KnownHeaderName, HeaderValues>,
40 unknown: HashMap<UnknownHeaderName<'static>, HeaderValues>,
41}
42
43pub const SERVER_HEADER: HeaderValue =
45 HeaderValue::const_new(concat!("trillium-http/", env!("CARGO_PKG_VERSION")));
46
47#[cfg(feature = "serde")]
48impl serde::Serialize for Headers {
49 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
50 where
51 S: serde::Serializer,
52 {
53 use serde::ser::SerializeMap;
54 let mut map = serializer.serialize_map(Some(self.len()))?;
55 for (key, values) in self {
56 map.serialize_entry(&key, values)?;
57 }
58 map.end()
59 }
60}
61
62impl Display for Headers {
63 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
64 let mut data = self.iter().collect::<Vec<_>>();
66 data.sort_by(|(a, _), (b, _)| a.cmp(b));
67 for (n, v) in data {
68 for v in v {
69 f.write_fmt(format_args!("{n}: {v}\r\n"))?;
70 }
71 }
72 Ok(())
73 }
74}
75
76#[cfg(feature = "parse")]
77impl Headers {
78 #[doc(hidden)]
79 pub fn extend_parse(&mut self, bytes: &[u8]) -> Result<usize, crate::Error> {
80 use memchr::memmem::Finder;
81
82 let mut new_header_count = 0;
83 let mut last_line = 0;
84 for newline in Finder::new(b"\r\n").find_iter(bytes) {
85 if newline == last_line {
86 continue;
87 }
88
89 let line = &bytes[last_line..newline];
90 let colon = memchr::memchr(b':', line).ok_or(crate::Error::InvalidHead)?;
91
92 let header_name = HeaderName::parse(&line[..colon])?.to_owned();
93
94 let token_end = last_line + colon;
95
96 let mut value_start = token_end + 1;
97
98 while bytes
99 .get(value_start)
100 .is_some_and(|b| matches!(b, b'\t' | b' '))
101 {
102 value_start += 1;
103 }
104
105 let header_value = HeaderValue::parse(bytes[value_start..newline].trim_ascii_end());
106 self.append(header_name, header_value);
107 new_header_count += 1;
108 last_line = newline + 2;
109 }
110 Ok(new_header_count)
111 }
112
113 #[doc(hidden)]
114 pub fn parse(bytes: &[u8]) -> Result<Self, crate::Error> {
115 let mut headers = Headers::new();
116 headers.extend_parse(bytes)?;
117 Ok(headers)
118 }
119}
120
121impl Headers {
122 pub fn new() -> Self {
124 Self::default()
125 }
126
127 pub fn iter(&self) -> Iter<'_> {
131 self.into()
132 }
133
134 pub fn is_empty(&self) -> bool {
136 self.known.is_empty() && self.unknown.is_empty()
137 }
138
139 pub fn len(&self) -> usize {
142 self.known.len() + self.unknown.len()
143 }
144
145 pub fn append(
152 &mut self,
153 name: impl Into<HeaderName<'static>>,
154 values: impl Into<HeaderValues>,
155 ) -> &mut HeaderValues {
156 self.entry(name).append(values)
157 }
158
159 pub fn append_all(&mut self, other: Headers) {
162 for (name, value) in other.known {
163 match self.known.entry(name) {
164 BTreeEntry::Occupied(mut entry) => {
165 entry.get_mut().extend(value);
166 }
167 BTreeEntry::Vacant(entry) => {
168 entry.insert(value);
169 }
170 }
171 }
172
173 for (name, value) in other.unknown {
174 match self.unknown.entry(name) {
175 HashbrownEntry::Occupied(mut entry) => {
176 entry.get_mut().extend(value);
177 }
178 HashbrownEntry::Vacant(entry) => {
179 entry.insert(value);
180 }
181 }
182 }
183 }
184
185 pub fn insert_all(&mut self, other: Headers) {
187 for (name, value) in other.known {
188 self.known.insert(name, value);
189 }
190
191 for (name, value) in other.unknown {
192 self.unknown.insert(name, value);
193 }
194 }
195
196 pub fn insert(
200 &mut self,
201 name: impl Into<HeaderName<'static>>,
202 values: impl Into<HeaderValues>,
203 ) -> &mut Self {
204 self.entry(name).insert(values);
205 self
206 }
207
208 pub fn try_insert(
213 &mut self,
214 name: impl Into<HeaderName<'static>>,
215 values: impl Into<HeaderValues>,
216 ) -> &mut Self {
217 self.entry(name).or_insert(values);
218 self
219 }
220
221 pub fn try_insert_with<V>(
226 &mut self,
227 name: impl Into<HeaderName<'static>>,
228 values: impl FnOnce() -> V,
229 ) -> &mut HeaderValues
230 where
231 V: Into<HeaderValues>,
232 {
233 self.entry(name).or_insert_with(values)
234 }
235
236 pub fn entry(&mut self, name: impl Into<HeaderName<'static>>) -> Entry<'_> {
240 match name.into().0 {
241 HeaderNameInner::KnownHeader(known) => match self.known.entry(known) {
242 BTreeEntry::Vacant(vacant) => {
243 Entry::Vacant(VacantEntry(VacantEntryInner::Known(vacant)))
244 }
245 BTreeEntry::Occupied(occupied) => {
246 Entry::Occupied(OccupiedEntry(OccupiedEntryInner::Known(occupied)))
247 }
248 },
249
250 HeaderNameInner::UnknownHeader(unknown) => match self.unknown.entry(unknown) {
251 HashbrownEntry::Occupied(occupied) => {
252 Entry::Occupied(OccupiedEntry(OccupiedEntryInner::Unknown(occupied)))
253 }
254
255 HashbrownEntry::Vacant(vacant) => {
256 Entry::Vacant(VacantEntry(VacantEntryInner::Unknown(vacant)))
257 }
258 },
259 }
260 }
261
262 pub fn get_str<'a>(&self, name: impl Into<HeaderName<'a>>) -> Option<&str> {
268 self.get_values(name).and_then(HeaderValues::as_str)
269 }
270
271 pub fn get<'a>(&self, name: impl Into<HeaderName<'a>>) -> Option<&HeaderValue> {
275 self.get_values(name).and_then(HeaderValues::one)
276 }
277
278 pub fn remove<'a>(&mut self, name: impl Into<HeaderName<'a>>) -> Option<HeaderValues> {
281 match name.into().0 {
282 HeaderNameInner::KnownHeader(known) => self.known.remove(&known),
283 HeaderNameInner::UnknownHeader(unknown) => self.unknown.remove(&&unknown),
284 }
285 }
286
287 pub fn get_values<'a>(&self, name: impl Into<HeaderName<'a>>) -> Option<&HeaderValues> {
291 match name.into().0 {
292 HeaderNameInner::KnownHeader(known) => self.known.get(&known),
293 HeaderNameInner::UnknownHeader(unknown) => self.unknown.get(&&unknown),
294 }
295 }
296
297 pub fn has_header<'a>(&self, name: impl Into<HeaderName<'a>>) -> bool {
302 match name.into().0 {
303 HeaderNameInner::KnownHeader(known) => self.known.contains_key(&known),
304 HeaderNameInner::UnknownHeader(unknown) => self.unknown.contains_key(&unknown),
305 }
306 }
307
308 pub fn eq_ignore_ascii_case<'a>(
313 &'a self,
314 name: impl Into<HeaderName<'a>>,
315 needle: &str,
316 ) -> bool {
317 self.get_str(name)
318 .is_some_and(|v| v.eq_ignore_ascii_case(needle))
319 }
320
321 pub fn with_inserted_header(
323 mut self,
324 name: impl Into<HeaderName<'static>>,
325 values: impl Into<HeaderValues>,
326 ) -> Self {
327 self.insert(name, values);
328 self
329 }
330
331 pub fn with_appended_header(
333 mut self,
334 name: impl Into<HeaderName<'static>>,
335 values: impl Into<HeaderValues>,
336 ) -> Self {
337 self.append(name, values);
338 self
339 }
340
341 pub fn without_header<'a>(mut self, name: impl Into<HeaderName<'a>>) -> Self {
343 self.remove(name);
344 self
345 }
346
347 pub fn without_headers<'a, I, H>(mut self, names: I) -> Self
349 where
350 I: IntoIterator<Item = H>,
351 H: Into<HeaderName<'a>>,
352 {
353 self.remove_all(names);
354 self
355 }
356
357 pub fn remove_all<'a, I, H>(&mut self, names: I)
359 where
360 I: IntoIterator<Item = H>,
361 H: Into<HeaderName<'a>>,
362 {
363 for name in names {
364 self.remove(name);
365 }
366 }
367}
368
369impl<HN, HV> Extend<(HN, HV)> for Headers
370where
371 HN: Into<HeaderName<'static>>,
372 HV: Into<HeaderValues>,
373{
374 fn extend<T: IntoIterator<Item = (HN, HV)>>(&mut self, iter: T) {
375 for (name, values) in iter {
376 self.append(name, values);
377 }
378 }
379}
380
381impl<HN, HV> FromIterator<(HN, HV)> for Headers
382where
383 HN: Into<HeaderName<'static>>,
384 HV: Into<HeaderValues>,
385{
386 fn from_iter<T: IntoIterator<Item = (HN, HV)>>(iter: T) -> Self {
387 let iter = iter.into_iter();
388 let mut headers = Self::new();
389 for (name, values) in iter {
390 headers.append(name, values);
391 }
392
393 headers
394 }
395}
396
397impl<'a> IntoIterator for &'a Headers {
398 type IntoIter = Iter<'a>;
399 type Item = (HeaderName<'a>, &'a HeaderValues);
400
401 fn into_iter(self) -> Self::IntoIter {
402 self.into()
403 }
404}
405
406#[derive(Debug)]
408pub struct IntoIter {
409 known: btree_map::IntoIter<KnownHeaderName, HeaderValues>,
410 unknown: hash_map::IntoIter<UnknownHeaderName<'static>, HeaderValues>,
411}
412
413impl Iterator for IntoIter {
414 type Item = (HeaderName<'static>, HeaderValues);
415
416 fn next(&mut self) -> Option<Self::Item> {
417 let IntoIter { known, unknown } = self;
418 known
419 .next()
420 .map(|(k, v)| (HeaderName::from(k), v))
421 .or_else(|| unknown.next().map(|(k, v)| (HeaderName::from(k), v)))
422 }
423}
424
425impl From<Headers> for IntoIter {
426 fn from(value: Headers) -> Self {
427 Self {
428 known: value.known.into_iter(),
429 unknown: value.unknown.into_iter(),
430 }
431 }
432}
433
434#[derive(Debug)]
436pub struct Iter<'a> {
437 known: btree_map::Iter<'a, KnownHeaderName, HeaderValues>,
438 unknown: hash_map::Iter<'a, UnknownHeaderName<'static>, HeaderValues>,
439}
440
441impl<'a> From<&'a Headers> for Iter<'a> {
442 fn from(value: &'a Headers) -> Self {
443 Iter {
444 known: value.known.iter(),
445 unknown: value.unknown.iter(),
446 }
447 }
448}
449
450impl<'a> Iterator for Iter<'a> {
451 type Item = (HeaderName<'a>, &'a HeaderValues);
452
453 fn next(&mut self) -> Option<Self::Item> {
454 let Iter { known, unknown } = self;
455 known
456 .next()
457 .map(|(k, v)| (HeaderName::from(*k), v))
458 .or_else(|| unknown.next().map(|(k, v)| (HeaderName::from(&**k), v)))
459 }
460}
461
462impl IntoIterator for Headers {
463 type IntoIter = IntoIter;
464 type Item = (HeaderName<'static>, HeaderValues);
465
466 fn into_iter(self) -> Self::IntoIter {
467 self.into()
468 }
469}