1use std::collections::{self, VecDeque, hash_map, hash_map::Entry};
2use std::fmt;
3
4use foldhash::fast::RandomState;
5
6use crate::{HeaderName, HeaderValue};
7
8type HashMap<K, V> = collections::HashMap<K, V, RandomState>;
9
10#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
13pub enum Either<A, B> {
14 Left(A),
16 Right(B),
18}
19
20#[derive(Clone, PartialEq, Eq)]
26pub struct HeaderMap {
27 pub(crate) inner: HashMap<HeaderName, Value>,
28}
29
30#[derive(Debug, Clone, PartialEq, Eq)]
31pub enum Value {
32 One(HeaderValue),
33 Multi(VecDeque<HeaderValue>),
34}
35
36impl Value {
37 fn get(&self) -> &HeaderValue {
38 match self {
39 Value::One(val) => val,
40 Value::Multi(val) => &val[0],
41 }
42 }
43
44 fn get_mut(&mut self) -> &mut HeaderValue {
45 match self {
46 Value::One(val) => val,
47 Value::Multi(val) => &mut val[0],
48 }
49 }
50
51 pub(crate) fn append(&mut self, val: HeaderValue) {
52 match self {
53 Value::One(prev_val) => {
54 let prev_val = std::mem::replace(prev_val, val);
55 let mut val = VecDeque::new();
56 val.push_back(prev_val);
57 let data = std::mem::replace(self, Value::Multi(val));
58 match data {
59 Value::One(val) => self.append(val),
60 Value::Multi(_) => unreachable!(),
61 }
62 }
63 Value::Multi(vec) => vec.push_back(val),
64 }
65 }
66}
67
68#[derive(Debug)]
69pub struct ValueIntoIter {
70 value: Value,
71}
72
73impl Iterator for ValueIntoIter {
74 type Item = HeaderValue;
75
76 fn next(&mut self) -> Option<Self::Item> {
77 match &mut self.value {
78 Value::One(_) => {
79 let val = std::mem::replace(
80 &mut self.value,
81 Value::Multi(VecDeque::with_capacity(0)),
82 );
83 match val {
84 Value::One(val) => Some(val),
85 Value::Multi(_) => unreachable!(),
86 }
87 }
88 Value::Multi(vec) => vec.pop_front(),
89 }
90 }
91
92 fn size_hint(&self) -> (usize, Option<usize>) {
93 match self.value {
94 Value::One(_) => (1, None),
95 Value::Multi(ref v) => v.iter().size_hint(),
96 }
97 }
98}
99
100impl IntoIterator for Value {
101 type Item = HeaderValue;
102 type IntoIter = ValueIntoIter;
103
104 #[inline]
105 fn into_iter(self) -> Self::IntoIter {
106 ValueIntoIter { value: self }
107 }
108}
109
110impl Extend<HeaderValue> for Value {
111 #[inline]
112 fn extend<T>(&mut self, iter: T)
113 where
114 T: IntoIterator<Item = HeaderValue>,
115 {
116 for h in iter {
117 self.append(h);
118 }
119 }
120}
121
122impl From<HeaderValue> for Value {
123 #[inline]
124 fn from(hdr: HeaderValue) -> Value {
125 Value::One(hdr)
126 }
127}
128
129impl<'a> From<&'a HeaderValue> for Value {
130 #[inline]
131 fn from(hdr: &'a HeaderValue) -> Value {
132 Value::One(hdr.clone())
133 }
134}
135
136impl Default for HeaderMap {
137 #[inline]
138 fn default() -> Self {
139 Self::new()
140 }
141}
142
143impl HeaderMap {
144 pub fn new() -> Self {
149 HeaderMap {
150 inner: HashMap::default(),
151 }
152 }
153
154 pub fn with_capacity(capacity: usize) -> HeaderMap {
163 HeaderMap {
164 inner: HashMap::with_capacity_and_hasher(capacity, RandomState::default()),
165 }
166 }
167
168 pub fn len(&self) -> usize {
173 self.inner.len()
174 }
175
176 pub fn is_empty(&self) -> bool {
178 self.inner.len() == 0
179 }
180
181 pub fn clear(&mut self) {
184 self.inner.clear();
185 }
186
187 pub fn capacity(&self) -> usize {
192 self.inner.capacity()
193 }
194
195 pub fn reserve(&mut self, additional: usize) {
204 self.inner.reserve(additional);
205 }
206
207 pub fn get<N: AsName>(&self, name: N) -> Option<&HeaderValue> {
213 self.get2(name).map(Value::get)
214 }
215
216 fn get2<N: AsName>(&self, name: N) -> Option<&Value> {
217 match name.as_name() {
218 Either::Left(name) => self.inner.get(name),
219 Either::Right(s) => {
220 if let Ok(name) = HeaderName::try_from(s) {
221 self.inner.get(&name)
222 } else {
223 None
224 }
225 }
226 }
227 }
228
229 pub fn get_all<N: AsName>(&self, name: N) -> GetAll<'_> {
237 GetAll {
238 idx: 0,
239 item: self.get2(name),
240 }
241 }
242
243 pub fn get_mut<N: AsName>(&mut self, name: N) -> Option<&mut HeaderValue> {
249 match name.as_name() {
250 Either::Left(name) => self.inner.get_mut(name).map(Value::get_mut),
251 Either::Right(s) => {
252 if let Ok(name) = HeaderName::try_from(s) {
253 self.inner.get_mut(&name).map(Value::get_mut)
254 } else {
255 None
256 }
257 }
258 }
259 }
260
261 pub fn contains_key<N: AsName>(&self, key: N) -> bool {
263 match key.as_name() {
264 Either::Left(name) => self.inner.contains_key(name),
265 Either::Right(s) => {
266 if let Ok(name) = HeaderName::try_from(s) {
267 self.inner.contains_key(&name)
268 } else {
269 false
270 }
271 }
272 }
273 }
274
275 pub fn iter(&self) -> Iter<'_> {
281 Iter::new(self.inner.iter())
282 }
283
284 #[doc(hidden)]
285 pub fn iter_inner(&self) -> hash_map::Iter<'_, HeaderName, Value> {
286 self.inner.iter()
287 }
288
289 pub fn keys(&self) -> Keys<'_> {
295 Keys(self.inner.keys())
296 }
297
298 pub fn insert(&mut self, key: HeaderName, val: HeaderValue) {
313 let _ = self.inner.insert(key, Value::One(val));
314 }
315
316 pub fn append(&mut self, key: HeaderName, value: HeaderValue) {
326 match self.inner.entry(key) {
327 Entry::Occupied(mut entry) => entry.get_mut().append(value),
328 Entry::Vacant(entry) => {
329 entry.insert(Value::One(value));
330 }
331 }
332 }
333
334 pub fn remove<N: AsName>(&mut self, key: N) {
336 match key.as_name() {
337 Either::Left(name) => {
338 let _ = self.inner.remove(name);
339 }
340 Either::Right(s) => {
341 if let Ok(name) = HeaderName::try_from(s) {
342 let _ = self.inner.remove(&name);
343 }
344 }
345 }
346 }
347}
348
349#[doc(hidden)]
350pub trait AsName {
351 fn as_name(&self) -> Either<&HeaderName, &str>;
352}
353
354impl AsName for HeaderName {
355 fn as_name(&self) -> Either<&HeaderName, &str> {
356 Either::Left(self)
357 }
358}
359
360impl AsName for &HeaderName {
361 fn as_name(&self) -> Either<&HeaderName, &str> {
362 Either::Left(self)
363 }
364}
365
366impl AsName for &str {
367 fn as_name(&self) -> Either<&HeaderName, &str> {
368 Either::Right(self)
369 }
370}
371
372impl AsName for String {
373 fn as_name(&self) -> Either<&HeaderName, &str> {
374 Either::Right(self.as_str())
375 }
376}
377
378impl AsName for &String {
379 fn as_name(&self) -> Either<&HeaderName, &str> {
380 Either::Right(self.as_str())
381 }
382}
383
384impl<N: std::fmt::Display, V> FromIterator<(N, V)> for HeaderMap
385where
386 HeaderName: TryFrom<N>,
387 Value: TryFrom<V>,
388 V: std::fmt::Debug,
389{
390 #[inline]
391 #[allow(clippy::mutable_key_type)]
392 fn from_iter<T: IntoIterator<Item = (N, V)>>(iter: T) -> Self {
393 let map = iter
394 .into_iter()
395 .filter_map(|(n, v)| {
396 let name = format!("{n}");
397 match (HeaderName::try_from(n), Value::try_from(v)) {
398 (Ok(n), Ok(v)) => Some((n, v)),
399 (Ok(n), Err(_)) => {
400 log::warn!("failed to parse `{n}` header value");
401 None
402 }
403 (Err(_), Ok(_)) => {
404 log::warn!("invalid HTTP header name: {name}");
405 None
406 }
407 (Err(_), Err(_)) => {
408 log::warn!("invalid HTTP header name `{name}` and value");
409 None
410 }
411 }
412 })
413 .fold(HashMap::default(), |mut map: HashMap<_, Value>, (n, v)| {
414 match map.entry(n) {
415 Entry::Occupied(mut oc) => oc.get_mut().extend(v),
416 Entry::Vacant(va) => {
417 let _ = va.insert(v);
418 }
419 }
420 map
421 });
422 HeaderMap { inner: map }
423 }
424}
425
426impl FromIterator<HeaderValue> for Value {
427 fn from_iter<T: IntoIterator<Item = HeaderValue>>(iter: T) -> Self {
428 let mut iter = iter.into_iter();
429 let value = iter.next().map(Value::One);
430 let mut value = match value {
431 Some(v) => v,
432 _ => Value::One(HeaderValue::from_static("")),
433 };
434 value.extend(iter);
435 value
436 }
437}
438
439impl TryFrom<&str> for Value {
440 type Error = crate::header::InvalidHeaderValue;
441 fn try_from(value: &str) -> Result<Self, Self::Error> {
442 Ok(value
443 .split(',')
444 .filter(|v| !v.is_empty())
445 .map(str::trim)
446 .filter_map(|v| HeaderValue::from_str(v).ok())
447 .collect::<Value>())
448 }
449}
450
451#[derive(Debug)]
452pub struct GetAll<'a> {
453 idx: usize,
454 item: Option<&'a Value>,
455}
456
457impl<'a> Iterator for GetAll<'a> {
458 type Item = &'a HeaderValue;
459
460 #[inline]
461 fn next(&mut self) -> Option<&'a HeaderValue> {
462 if let Some(ref val) = self.item {
463 match val {
464 Value::One(val) => {
465 self.item.take();
466 Some(val)
467 }
468 Value::Multi(vec) => {
469 if self.idx < vec.len() {
470 let item = Some(&vec[self.idx]);
471 self.idx += 1;
472 item
473 } else {
474 self.item.take();
475 None
476 }
477 }
478 }
479 } else {
480 None
481 }
482 }
483}
484
485#[derive(Debug)]
486pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);
487
488impl<'a> Iterator for Keys<'a> {
489 type Item = &'a HeaderName;
490
491 #[inline]
492 fn next(&mut self) -> Option<&'a HeaderName> {
493 self.0.next()
494 }
495}
496
497impl<'a> IntoIterator for &'a HeaderMap {
498 type Item = (&'a HeaderName, &'a HeaderValue);
499 type IntoIter = Iter<'a>;
500
501 fn into_iter(self) -> Self::IntoIter {
502 self.iter()
503 }
504}
505
506#[derive(Debug)]
507pub struct Iter<'a> {
508 idx: usize,
509 current: Option<(&'a HeaderName, &'a VecDeque<HeaderValue>)>,
510 inner: hash_map::Iter<'a, HeaderName, Value>,
511}
512
513impl<'a> Iter<'a> {
514 fn new(inner: hash_map::Iter<'a, HeaderName, Value>) -> Self {
515 Self {
516 inner,
517 idx: 0,
518 current: None,
519 }
520 }
521}
522
523impl<'a> Iterator for Iter<'a> {
524 type Item = (&'a HeaderName, &'a HeaderValue);
525
526 #[inline]
527 fn next(&mut self) -> Option<(&'a HeaderName, &'a HeaderValue)> {
528 if let Some(ref mut item) = self.current {
529 if self.idx < item.1.len() {
530 let item = (item.0, &item.1[self.idx]);
531 self.idx += 1;
532 return Some(item);
533 }
534 self.idx = 0;
535 self.current.take();
536 }
537 if let Some(item) = self.inner.next() {
538 match item.1 {
539 Value::One(value) => Some((item.0, value)),
540 Value::Multi(vec) => {
541 self.current = Some((item.0, vec));
542 self.next()
543 }
544 }
545 } else {
546 None
547 }
548 }
549}
550
551impl fmt::Debug for HeaderMap {
552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
553 let mut f = f.debug_map();
554
555 for (key, val) in &self.inner {
556 match val {
557 Value::One(val) => {
558 let _ = f.entry(&key, &val);
559 }
560 Value::Multi(val) => {
561 for v in val {
562 f.entry(&key, &v);
563 }
564 }
565 }
566 }
567 f.finish()
568 }
569}
570
571#[cfg(test)]
572mod tests {
573 use super::*;
574 use crate::header::{ACCEPT_ENCODING, CONTENT_TYPE};
575
576 #[test]
577 fn test_from_iter() {
578 let vec = vec![
579 ("Connection", "keep-alive"),
580 ("Accept", "text/html"),
581 (
582 "Accept",
583 "*/*, application/xhtml+xml, application/xml;q=0.9, image/webp,",
584 ),
585 ];
586 let map = HeaderMap::from_iter(vec);
587 assert_eq!(
588 map.get("Connection"),
589 Some(&HeaderValue::from_static("keep-alive"))
590 );
591 assert_eq!(
592 map.get_all("Accept").collect::<Vec<&HeaderValue>>(),
593 vec![
594 &HeaderValue::from_static("text/html"),
595 &HeaderValue::from_static("*/*"),
596 &HeaderValue::from_static("application/xhtml+xml"),
597 &HeaderValue::from_static("application/xml;q=0.9"),
598 &HeaderValue::from_static("image/webp"),
599 ]
600 );
601 }
602
603 #[test]
604 #[allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args)]
605 fn test_basics() {
606 let m = HeaderMap::default();
607 assert!(m.is_empty());
608 let mut m = HeaderMap::with_capacity(10);
609 assert!(m.is_empty());
610 assert!(m.capacity() >= 10);
611 m.reserve(20);
612 assert!(m.capacity() >= 20);
613
614 m.insert(CONTENT_TYPE, HeaderValue::from_static("text"));
615 assert!(m.contains_key(CONTENT_TYPE));
616 assert!(m.contains_key("content-type"));
617 assert!(m.contains_key("content-type".to_string()));
618 assert!(m.contains_key(&("content-type".to_string())));
619 assert_eq!(
620 *m.get_mut("content-type").unwrap(),
621 HeaderValue::from_static("text")
622 );
623 assert_eq!(
624 *m.get_mut(CONTENT_TYPE).unwrap(),
625 HeaderValue::from_static("text")
626 );
627 assert!(format!("{m:?}").contains("content-type"));
628
629 assert!(m.keys().any(|x| x == CONTENT_TYPE));
630 m.remove("content-type");
631 assert!(m.is_empty());
632 }
633
634 #[test]
635 fn test_append() {
636 let mut map = HeaderMap::new();
637
638 map.append(ACCEPT_ENCODING, HeaderValue::from_static("gzip"));
639 assert_eq!(
640 map.get_all(ACCEPT_ENCODING).collect::<Vec<_>>(),
641 vec![&HeaderValue::from_static("gzip"),]
642 );
643
644 map.append(ACCEPT_ENCODING, HeaderValue::from_static("br"));
645 map.append(ACCEPT_ENCODING, HeaderValue::from_static("deflate"));
646 assert_eq!(
647 map.get_all(ACCEPT_ENCODING).collect::<Vec<_>>(),
648 vec![
649 &HeaderValue::from_static("gzip"),
650 &HeaderValue::from_static("br"),
651 &HeaderValue::from_static("deflate"),
652 ]
653 );
654 assert_eq!(
655 map.get(ACCEPT_ENCODING),
656 Some(&HeaderValue::from_static("gzip"))
657 );
658 assert_eq!(
659 map.get_mut(ACCEPT_ENCODING),
660 Some(&mut HeaderValue::from_static("gzip"))
661 );
662
663 map.remove(ACCEPT_ENCODING);
664 assert_eq!(map.get(ACCEPT_ENCODING), None);
665 }
666
667 #[test]
668 fn test_from_http() {
669 let mut map = http::HeaderMap::new();
670 map.append(ACCEPT_ENCODING, http::HeaderValue::from_static("gzip"));
671
672 let map2 = HeaderMap::from(map);
673 assert_eq!(
674 map2.get(ACCEPT_ENCODING),
675 Some(&HeaderValue::from_static("gzip"))
676 );
677 }
678}