Skip to main content

actix_http/header/
map.rs

1//! A multi-value [`HeaderMap`] and its iterators.
2
3use std::{borrow::Cow, collections::hash_map, iter, ops};
4
5use foldhash::{HashMap as FoldHashMap, HashMapExt as _};
6use http::header::{HeaderName, HeaderValue};
7use smallvec::{smallvec, SmallVec};
8
9use super::AsHeaderName;
10
11/// A multi-map of HTTP headers.
12///
13/// `HeaderMap` is a "multi-map" of [`HeaderName`] to one or more [`HeaderValue`]s.
14///
15/// # Examples
16///
17/// ```
18/// # use actix_http::header::{self, HeaderMap, HeaderValue};
19///
20/// let mut map = HeaderMap::new();
21///
22/// map.insert(header::CONTENT_TYPE, HeaderValue::from_static("text/plain"));
23/// map.insert(header::ORIGIN, HeaderValue::from_static("example.com"));
24///
25/// assert!(map.contains_key(header::CONTENT_TYPE));
26/// assert!(map.contains_key(header::ORIGIN));
27///
28/// let mut removed = map.remove(header::ORIGIN);
29/// assert_eq!(removed.next().unwrap(), "example.com");
30///
31/// assert!(!map.contains_key(header::ORIGIN));
32/// ```
33///
34/// Construct a header map using the [`FromIterator`] implementation. Note that it uses the append
35/// strategy, so duplicate header names are preserved.
36///
37/// ```
38/// use actix_http::header::{self, HeaderMap, HeaderValue};
39///
40/// let headers = HeaderMap::from_iter([
41///     (header::CONTENT_TYPE, HeaderValue::from_static("text/plain")),
42///     (header::COOKIE, HeaderValue::from_static("foo=1")),
43///     (header::COOKIE, HeaderValue::from_static("bar=1")),
44/// ]);
45///
46/// assert_eq!(headers.len(), 3);
47/// ```
48#[derive(Debug, Clone, Default)]
49pub struct HeaderMap {
50    pub(crate) inner: FoldHashMap<HeaderName, Value>,
51}
52
53/// A bespoke non-empty list for HeaderMap values.
54#[derive(Debug, Clone)]
55pub(crate) struct Value {
56    inner: SmallVec<[HeaderValue; 4]>,
57}
58
59impl Value {
60    fn one(val: HeaderValue) -> Self {
61        Self {
62            inner: smallvec![val],
63        }
64    }
65
66    fn first(&self) -> &HeaderValue {
67        &self.inner[0]
68    }
69
70    fn first_mut(&mut self) -> &mut HeaderValue {
71        &mut self.inner[0]
72    }
73
74    fn append(&mut self, new_val: HeaderValue) {
75        self.inner.push(new_val)
76    }
77}
78
79impl ops::Deref for Value {
80    type Target = SmallVec<[HeaderValue; 4]>;
81
82    fn deref(&self) -> &Self::Target {
83        &self.inner
84    }
85}
86
87impl HeaderMap {
88    /// Create an empty `HeaderMap`.
89    ///
90    /// The map will be created without any capacity; this function will not allocate.
91    ///
92    /// # Examples
93    /// ```
94    /// # use actix_http::header::HeaderMap;
95    /// let map = HeaderMap::new();
96    ///
97    /// assert!(map.is_empty());
98    /// assert_eq!(0, map.capacity());
99    /// ```
100    pub fn new() -> Self {
101        HeaderMap::default()
102    }
103
104    /// Create an empty `HeaderMap` with the specified capacity.
105    ///
106    /// The map will be able to hold at least `capacity` elements without needing to reallocate.
107    /// If `capacity` is 0, the map will be created without allocating.
108    ///
109    /// # Examples
110    /// ```
111    /// # use actix_http::header::HeaderMap;
112    /// let map = HeaderMap::with_capacity(16);
113    ///
114    /// assert!(map.is_empty());
115    /// assert!(map.capacity() >= 16);
116    /// ```
117    pub fn with_capacity(capacity: usize) -> Self {
118        HeaderMap {
119            inner: FoldHashMap::with_capacity(capacity),
120        }
121    }
122
123    /// Create new `HeaderMap` from a `http::HeaderMap`-like drain.
124    pub(crate) fn from_drain<I>(mut drain: I) -> Self
125    where
126        I: Iterator<Item = (Option<HeaderName>, HeaderValue)>,
127    {
128        let (first_name, first_value) = match drain.next() {
129            None => return HeaderMap::new(),
130            Some((name, val)) => {
131                let name = name.expect("drained first item had no name");
132                (name, val)
133            }
134        };
135
136        let (lb, ub) = drain.size_hint();
137        let capacity = ub.unwrap_or(lb);
138
139        let mut map = HeaderMap::with_capacity(capacity);
140        map.append(first_name.clone(), first_value);
141
142        let (map, _) = drain.fold((map, first_name), |(mut map, prev_name), (name, value)| {
143            let name = name.unwrap_or(prev_name);
144            map.append(name.clone(), value);
145            (map, name)
146        });
147
148        map
149    }
150
151    /// Returns the number of values stored in the map.
152    ///
153    /// See also: [`len_keys`](Self::len_keys).
154    ///
155    /// # Examples
156    /// ```
157    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
158    /// let mut map = HeaderMap::new();
159    /// assert_eq!(map.len(), 0);
160    ///
161    /// map.insert(header::ACCEPT, HeaderValue::from_static("text/plain"));
162    /// map.insert(header::SET_COOKIE, HeaderValue::from_static("one=1"));
163    /// assert_eq!(map.len(), 2);
164    ///
165    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
166    /// assert_eq!(map.len(), 3);
167    /// ```
168    pub fn len(&self) -> usize {
169        self.inner.values().map(|vals| vals.len()).sum()
170    }
171
172    /// Returns the number of _keys_ stored in the map.
173    ///
174    /// The number of values stored will be at least this number. See also: [`Self::len`].
175    ///
176    /// # Examples
177    /// ```
178    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
179    /// let mut map = HeaderMap::new();
180    /// assert_eq!(map.len_keys(), 0);
181    ///
182    /// map.insert(header::ACCEPT, HeaderValue::from_static("text/plain"));
183    /// map.insert(header::SET_COOKIE, HeaderValue::from_static("one=1"));
184    /// assert_eq!(map.len_keys(), 2);
185    ///
186    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
187    /// assert_eq!(map.len_keys(), 2);
188    /// ```
189    pub fn len_keys(&self) -> usize {
190        self.inner.len()
191    }
192
193    /// Returns true if the map contains no elements.
194    ///
195    /// # Examples
196    /// ```
197    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
198    /// let mut map = HeaderMap::new();
199    /// assert!(map.is_empty());
200    ///
201    /// map.insert(header::ACCEPT, HeaderValue::from_static("text/plain"));
202    /// assert!(!map.is_empty());
203    /// ```
204    pub fn is_empty(&self) -> bool {
205        self.inner.len() == 0
206    }
207
208    /// Clears the map, removing all name-value pairs.
209    ///
210    /// Keeps the allocated memory for reuse.
211    ///
212    /// # Examples
213    /// ```
214    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
215    /// let mut map = HeaderMap::new();
216    ///
217    /// map.insert(header::ACCEPT, HeaderValue::from_static("text/plain"));
218    /// map.insert(header::SET_COOKIE, HeaderValue::from_static("one=1"));
219    /// assert_eq!(map.len(), 2);
220    ///
221    /// map.clear();
222    /// assert!(map.is_empty());
223    /// ```
224    pub fn clear(&mut self) {
225        self.inner.clear();
226    }
227
228    fn get_value(&self, key: impl AsHeaderName) -> Option<&Value> {
229        match key.try_as_name(super::as_name::Seal).ok()? {
230            Cow::Borrowed(name) => self.inner.get(name),
231            Cow::Owned(name) => self.inner.get(&name),
232        }
233    }
234
235    /// Returns a reference to the _first_ value associated with a header name.
236    ///
237    /// Returns `None` if there is no value associated with the key.
238    ///
239    /// Even when multiple values are associated with the key, the "first" one is returned but is
240    /// not guaranteed to be chosen with any particular order; though, the returned item will be
241    /// consistent for each call to `get` if the map has not changed.
242    ///
243    /// See also: [`get_all`](Self::get_all).
244    ///
245    /// # Examples
246    /// ```
247    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
248    /// let mut map = HeaderMap::new();
249    ///
250    /// map.insert(header::SET_COOKIE, HeaderValue::from_static("one=1"));
251    ///
252    /// let cookie = map.get(header::SET_COOKIE).unwrap();
253    /// assert_eq!(cookie, "one=1");
254    ///
255    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
256    /// assert_eq!(map.get(header::SET_COOKIE).unwrap(), "one=1");
257    ///
258    /// assert_eq!(map.get(header::SET_COOKIE), map.get("set-cookie"));
259    /// assert_eq!(map.get(header::SET_COOKIE), map.get("Set-Cookie"));
260    ///
261    /// assert!(map.get(header::HOST).is_none());
262    /// assert!(map.get("INVALID HEADER NAME").is_none());
263    /// ```
264    pub fn get(&self, key: impl AsHeaderName) -> Option<&HeaderValue> {
265        self.get_value(key).map(Value::first)
266    }
267
268    /// Returns a mutable reference to the _first_ value associated a header name.
269    ///
270    /// Returns `None` if there is no value associated with the key.
271    ///
272    /// Even when multiple values are associated with the key, the "first" one is returned but is
273    /// not guaranteed to be chosen with any particular order; though, the returned item will be
274    /// consistent for each call to `get_mut` if the map has not changed.
275    ///
276    /// See also: [`get_all`](Self::get_all).
277    ///
278    /// # Examples
279    /// ```
280    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
281    /// let mut map = HeaderMap::new();
282    ///
283    /// map.insert(header::SET_COOKIE, HeaderValue::from_static("one=1"));
284    ///
285    /// let mut cookie = map.get_mut(header::SET_COOKIE).unwrap();
286    /// assert_eq!(cookie, "one=1");
287    ///
288    /// *cookie = HeaderValue::from_static("three=3");
289    /// assert_eq!(map.get(header::SET_COOKIE).unwrap(), "three=3");
290    ///
291    /// assert!(map.get(header::HOST).is_none());
292    /// assert!(map.get("INVALID HEADER NAME").is_none());
293    /// ```
294    pub fn get_mut(&mut self, key: impl AsHeaderName) -> Option<&mut HeaderValue> {
295        match key.try_as_name(super::as_name::Seal).ok()? {
296            Cow::Borrowed(name) => self.inner.get_mut(name).map(Value::first_mut),
297            Cow::Owned(name) => self.inner.get_mut(&name).map(Value::first_mut),
298        }
299    }
300
301    /// Returns an iterator over all values associated with a header name.
302    ///
303    /// The returned iterator does not incur any allocations and will yield no items if there are no
304    /// values associated with the key. Iteration order is guaranteed to be the same as
305    /// insertion order.
306    ///
307    /// # Examples
308    /// ```
309    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
310    /// let mut map = HeaderMap::new();
311    ///
312    /// let mut none_iter = map.get_all(header::ORIGIN);
313    /// assert!(none_iter.next().is_none());
314    ///
315    /// map.insert(header::SET_COOKIE, HeaderValue::from_static("one=1"));
316    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
317    ///
318    /// let mut set_cookies_iter = map.get_all(header::SET_COOKIE);
319    /// assert_eq!(set_cookies_iter.next().unwrap(), "one=1");
320    /// assert_eq!(set_cookies_iter.next().unwrap(), "two=2");
321    /// assert!(set_cookies_iter.next().is_none());
322    /// ```
323    pub fn get_all(&self, key: impl AsHeaderName) -> std::slice::Iter<'_, HeaderValue> {
324        match self.get_value(key) {
325            Some(value) => value.iter(),
326            None => [].iter(),
327        }
328    }
329
330    // TODO: get_all_mut ?
331
332    /// Returns `true` if the map contains a value for the specified key.
333    ///
334    /// Invalid header names will simply return false.
335    ///
336    /// # Examples
337    /// ```
338    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
339    /// let mut map = HeaderMap::new();
340    /// assert!(!map.contains_key(header::ACCEPT));
341    ///
342    /// map.insert(header::ACCEPT, HeaderValue::from_static("text/plain"));
343    /// assert!(map.contains_key(header::ACCEPT));
344    /// ```
345    pub fn contains_key(&self, key: impl AsHeaderName) -> bool {
346        match key.try_as_name(super::as_name::Seal) {
347            Ok(Cow::Borrowed(name)) => self.inner.contains_key(name),
348            Ok(Cow::Owned(name)) => self.inner.contains_key(&name),
349            Err(_) => false,
350        }
351    }
352
353    /// Inserts (overrides) a name-value pair in the map.
354    ///
355    /// If the map already contained this key, the new value is associated with the key and all
356    /// previous values are removed and returned as a `Removed` iterator. The key is not updated;
357    /// this matters for types that can be `==` without being identical.
358    ///
359    /// # Examples
360    /// ```
361    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
362    /// let mut map = HeaderMap::new();
363    ///
364    /// map.insert(header::ACCEPT, HeaderValue::from_static("text/plain"));
365    /// assert!(map.contains_key(header::ACCEPT));
366    /// assert_eq!(map.len(), 1);
367    ///
368    /// let mut removed = map.insert(header::ACCEPT, HeaderValue::from_static("text/csv"));
369    /// assert_eq!(removed.next().unwrap(), "text/plain");
370    /// assert!(removed.next().is_none());
371    ///
372    /// assert_eq!(map.len(), 1);
373    /// ```
374    ///
375    /// A convenience method is provided on the returned iterator to check if the insertion replaced
376    /// any values.
377    /// ```
378    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
379    /// let mut map = HeaderMap::new();
380    ///
381    /// let removed = map.insert(header::ACCEPT, HeaderValue::from_static("text/plain"));
382    /// assert!(removed.is_empty());
383    ///
384    /// let removed = map.insert(header::ACCEPT, HeaderValue::from_static("text/html"));
385    /// assert!(!removed.is_empty());
386    /// ```
387    pub fn insert(&mut self, name: HeaderName, val: HeaderValue) -> Removed {
388        let value = self.inner.insert(name, Value::one(val));
389        Removed::new(value)
390    }
391
392    /// Appends a name-value pair to the map.
393    ///
394    /// If the map already contained this key, the new value is added to the list of values
395    /// currently associated with the key. The key is not updated; this matters for types that can
396    /// be `==` without being identical.
397    ///
398    /// # Examples
399    /// ```
400    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
401    /// let mut map = HeaderMap::new();
402    ///
403    /// map.append(header::HOST, HeaderValue::from_static("example.com"));
404    /// assert_eq!(map.len(), 1);
405    ///
406    /// map.append(header::ACCEPT, HeaderValue::from_static("text/csv"));
407    /// assert_eq!(map.len(), 2);
408    ///
409    /// map.append(header::ACCEPT, HeaderValue::from_static("text/html"));
410    /// assert_eq!(map.len(), 3);
411    /// ```
412    pub fn append(&mut self, key: HeaderName, value: HeaderValue) {
413        match self.inner.entry(key) {
414            hash_map::Entry::Occupied(mut entry) => {
415                entry.get_mut().append(value);
416            }
417            hash_map::Entry::Vacant(entry) => {
418                entry.insert(Value::one(value));
419            }
420        };
421    }
422
423    /// Removes all headers for a particular header name from the map.
424    ///
425    /// Providing an invalid header names (as a string argument) will have no effect and return
426    /// without error.
427    ///
428    /// # Examples
429    /// ```
430    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
431    /// let mut map = HeaderMap::new();
432    ///
433    /// map.append(header::SET_COOKIE, HeaderValue::from_static("one=1"));
434    /// map.append(header::SET_COOKIE, HeaderValue::from_static("one=2"));
435    ///
436    /// assert_eq!(map.len(), 2);
437    ///
438    /// let mut removed = map.remove(header::SET_COOKIE);
439    /// assert_eq!(removed.next().unwrap(), "one=1");
440    /// assert_eq!(removed.next().unwrap(), "one=2");
441    /// assert!(removed.next().is_none());
442    ///
443    /// assert!(map.is_empty());
444    /// ```
445    ///
446    /// A convenience method is provided on the returned iterator to check if the `remove` call
447    /// actually removed any values.
448    /// ```
449    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
450    /// let mut map = HeaderMap::new();
451    ///
452    /// let removed = map.remove("accept");
453    /// assert!(removed.is_empty());
454    ///
455    /// map.insert(header::ACCEPT, HeaderValue::from_static("text/html"));
456    /// let removed = map.remove("accept");
457    /// assert!(!removed.is_empty());
458    /// ```
459    pub fn remove(&mut self, key: impl AsHeaderName) -> Removed {
460        let value = match key.try_as_name(super::as_name::Seal) {
461            Ok(Cow::Borrowed(name)) => self.inner.remove(name),
462            Ok(Cow::Owned(name)) => self.inner.remove(&name),
463            Err(_) => None,
464        };
465
466        Removed::new(value)
467    }
468
469    /// Returns the number of single-value headers the map can hold without needing to reallocate.
470    ///
471    /// Since this is a multi-value map, the actual capacity is much larger when considering
472    /// each header name can be associated with an arbitrary number of values. The effect is that
473    /// the size of `len` may be greater than `capacity` since it counts all the values.
474    /// Conversely, [`len_keys`](Self::len_keys) will never be larger than capacity.
475    ///
476    /// # Examples
477    /// ```
478    /// # use actix_http::header::HeaderMap;
479    /// let map = HeaderMap::with_capacity(16);
480    ///
481    /// assert!(map.is_empty());
482    /// assert!(map.capacity() >= 16);
483    /// ```
484    pub fn capacity(&self) -> usize {
485        self.inner.capacity()
486    }
487
488    /// Reserves capacity for at least `additional` more headers to be inserted in the map.
489    ///
490    /// The header map may reserve more space to avoid frequent reallocations. Additional capacity
491    /// only considers single-value headers.
492    ///
493    /// # Panics
494    /// Panics if the new allocation size overflows usize.
495    ///
496    /// # Examples
497    /// ```
498    /// # use actix_http::header::HeaderMap;
499    /// let mut map = HeaderMap::with_capacity(2);
500    /// assert!(map.capacity() >= 2);
501    ///
502    /// map.reserve(100);
503    /// assert!(map.capacity() >= 102);
504    ///
505    /// assert!(map.is_empty());
506    /// ```
507    pub fn reserve(&mut self, additional: usize) {
508        self.inner.reserve(additional)
509    }
510
511    /// An iterator over all name-value pairs.
512    ///
513    /// Names will be yielded for each associated value. So, if a key has 3 associated values, it
514    /// will be yielded 3 times. The iteration order should be considered arbitrary.
515    ///
516    /// # Examples
517    /// ```
518    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
519    /// let mut map = HeaderMap::new();
520    ///
521    /// let mut iter = map.iter();
522    /// assert!(iter.next().is_none());
523    ///
524    /// map.append(header::HOST, HeaderValue::from_static("duck.com"));
525    /// map.append(header::SET_COOKIE, HeaderValue::from_static("one=1"));
526    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
527    ///
528    /// let mut iter = map.iter();
529    /// assert!(iter.next().is_some());
530    /// assert!(iter.next().is_some());
531    /// assert!(iter.next().is_some());
532    /// assert!(iter.next().is_none());
533    ///
534    /// let pairs = map.iter().collect::<Vec<_>>();
535    /// assert!(pairs.contains(&(&header::HOST, &HeaderValue::from_static("duck.com"))));
536    /// assert!(pairs.contains(&(&header::SET_COOKIE, &HeaderValue::from_static("one=1"))));
537    /// assert!(pairs.contains(&(&header::SET_COOKIE, &HeaderValue::from_static("two=2"))));
538    /// ```
539    pub fn iter(&self) -> Iter<'_> {
540        Iter::new(self.inner.iter(), self.len())
541    }
542
543    /// An iterator over all contained header names.
544    ///
545    /// Each name will only be yielded once even if it has multiple associated values. The iteration
546    /// order should be considered arbitrary.
547    ///
548    /// # Examples
549    /// ```
550    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
551    /// let mut map = HeaderMap::new();
552    ///
553    /// let mut iter = map.keys();
554    /// assert!(iter.next().is_none());
555    ///
556    /// map.append(header::HOST, HeaderValue::from_static("duck.com"));
557    /// map.append(header::SET_COOKIE, HeaderValue::from_static("one=1"));
558    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
559    ///
560    /// let keys = map.keys().cloned().collect::<Vec<_>>();
561    /// assert_eq!(keys.len(), 2);
562    /// assert!(keys.contains(&header::HOST));
563    /// assert!(keys.contains(&header::SET_COOKIE));
564    /// ```
565    pub fn keys(&self) -> Keys<'_> {
566        Keys(self.inner.keys())
567    }
568
569    /// Retains only the headers specified by the predicate.
570    ///
571    /// In other words, removes all headers `(name, val)` for which `retain_fn(&name, &mut val)`
572    /// returns false.
573    ///
574    /// The order in which headers are visited should be considered arbitrary.
575    ///
576    /// # Examples
577    /// ```
578    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
579    /// let mut map = HeaderMap::new();
580    ///
581    /// map.append(header::HOST, HeaderValue::from_static("duck.com"));
582    /// map.append(header::SET_COOKIE, HeaderValue::from_static("one=1"));
583    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
584    ///
585    /// map.retain(|name, val| val.as_bytes().starts_with(b"one"));
586    ///
587    /// assert_eq!(map.len(), 1);
588    /// assert!(map.contains_key(&header::SET_COOKIE));
589    /// ```
590    pub fn retain<F>(&mut self, mut retain_fn: F)
591    where
592        F: FnMut(&HeaderName, &mut HeaderValue) -> bool,
593    {
594        self.inner.retain(|name, vals| {
595            vals.inner.retain(|val| retain_fn(name, val));
596
597            // invariant: make sure newly empty value lists are removed
598            !vals.is_empty()
599        })
600    }
601
602    /// Clears the map, returning all name-value sets as an iterator.
603    ///
604    /// Header names will only be yielded for the first value in each set. All items that are
605    /// yielded without a name and after an item with a name are associated with that same name.
606    /// The first item will always contain a name.
607    ///
608    /// Keeps the allocated memory for reuse.
609    /// # Examples
610    /// ```
611    /// # use actix_http::header::{self, HeaderMap, HeaderValue};
612    /// let mut map = HeaderMap::new();
613    ///
614    /// let mut iter = map.drain();
615    /// assert!(iter.next().is_none());
616    /// drop(iter);
617    ///
618    /// map.append(header::SET_COOKIE, HeaderValue::from_static("one=1"));
619    /// map.append(header::SET_COOKIE, HeaderValue::from_static("two=2"));
620    ///
621    /// let mut iter = map.drain();
622    /// assert_eq!(iter.next().unwrap(), (Some(header::SET_COOKIE), HeaderValue::from_static("one=1")));
623    /// assert_eq!(iter.next().unwrap(), (None, HeaderValue::from_static("two=2")));
624    /// drop(iter);
625    ///
626    /// assert!(map.is_empty());
627    /// ```
628    pub fn drain(&mut self) -> Drain<'_> {
629        let len = self.len();
630        Drain::new(self.inner.drain(), len)
631    }
632}
633
634/// Note that this implementation will clone a [HeaderName] for each value. Consider using
635/// [`drain`](Self::drain) to control header name cloning.
636impl IntoIterator for HeaderMap {
637    type Item = (HeaderName, HeaderValue);
638    type IntoIter = IntoIter;
639
640    #[inline]
641    fn into_iter(self) -> Self::IntoIter {
642        let len = self.len();
643        IntoIter::new(self.inner.into_iter(), len)
644    }
645}
646
647impl<'a> IntoIterator for &'a HeaderMap {
648    type Item = (&'a HeaderName, &'a HeaderValue);
649    type IntoIter = Iter<'a>;
650
651    #[inline]
652    fn into_iter(self) -> Self::IntoIter {
653        Iter::new(self.inner.iter(), self.len())
654    }
655}
656
657impl FromIterator<(HeaderName, HeaderValue)> for HeaderMap {
658    fn from_iter<T: IntoIterator<Item = (HeaderName, HeaderValue)>>(iter: T) -> Self {
659        iter.into_iter()
660            .fold(Self::new(), |mut map, (name, value)| {
661                map.append(name, value);
662                map
663            })
664    }
665}
666
667/// Convert a `http::HeaderMap` to our `HeaderMap`.
668impl From<http::HeaderMap> for HeaderMap {
669    fn from(mut map: http::HeaderMap) -> Self {
670        Self::from_drain(map.drain())
671    }
672}
673
674/// Convert our `HeaderMap` to a `http::HeaderMap`.
675impl From<HeaderMap> for http::HeaderMap {
676    fn from(map: HeaderMap) -> Self {
677        Self::from_iter(map)
678    }
679}
680
681/// Convert our `&HeaderMap` to a `http::HeaderMap`.
682impl From<&HeaderMap> for http::HeaderMap {
683    fn from(map: &HeaderMap) -> Self {
684        map.to_owned().into()
685    }
686}
687
688/// Iterator over removed, owned values with the same associated name.
689///
690/// Returned from methods that remove or replace items. See [`HeaderMap::insert`]
691/// and [`HeaderMap::remove`].
692#[derive(Debug)]
693pub struct Removed {
694    inner: Option<smallvec::IntoIter<[HeaderValue; 4]>>,
695}
696
697impl Removed {
698    fn new(value: Option<Value>) -> Self {
699        let inner = value.map(|value| value.inner.into_iter());
700        Self { inner }
701    }
702
703    /// Returns true if iterator contains no elements, without consuming it.
704    ///
705    /// If called immediately after [`HeaderMap::insert`] or [`HeaderMap::remove`], it will indicate
706    /// whether any items were actually replaced or removed, respectively.
707    pub fn is_empty(&self) -> bool {
708        match self.inner {
709            // size hint lower bound of smallvec is the correct length
710            Some(ref iter) => iter.size_hint().0 == 0,
711            None => true,
712        }
713    }
714}
715
716impl Iterator for Removed {
717    type Item = HeaderValue;
718
719    #[inline]
720    fn next(&mut self) -> Option<Self::Item> {
721        self.inner.as_mut()?.next()
722    }
723
724    #[inline]
725    fn size_hint(&self) -> (usize, Option<usize>) {
726        match self.inner {
727            Some(ref iter) => iter.size_hint(),
728            None => (0, None),
729        }
730    }
731}
732
733impl ExactSizeIterator for Removed {}
734
735impl iter::FusedIterator for Removed {}
736
737/// Iterator over all names in the map.
738#[derive(Debug)]
739pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);
740
741impl<'a> Iterator for Keys<'a> {
742    type Item = &'a HeaderName;
743
744    #[inline]
745    fn next(&mut self) -> Option<Self::Item> {
746        self.0.next()
747    }
748
749    #[inline]
750    fn size_hint(&self) -> (usize, Option<usize>) {
751        self.0.size_hint()
752    }
753}
754
755impl ExactSizeIterator for Keys<'_> {}
756
757impl iter::FusedIterator for Keys<'_> {}
758
759/// Iterator over borrowed name-value pairs.
760#[derive(Debug)]
761pub struct Iter<'a> {
762    inner: hash_map::Iter<'a, HeaderName, Value>,
763    multi_inner: Option<(&'a HeaderName, &'a SmallVec<[HeaderValue; 4]>)>,
764    multi_idx: usize,
765    remaining: usize,
766}
767
768impl<'a> Iter<'a> {
769    fn new(iter: hash_map::Iter<'a, HeaderName, Value>, remaining: usize) -> Self {
770        Self {
771            inner: iter,
772            multi_idx: 0,
773            multi_inner: None,
774            remaining,
775        }
776    }
777}
778
779impl<'a> Iterator for Iter<'a> {
780    type Item = (&'a HeaderName, &'a HeaderValue);
781
782    fn next(&mut self) -> Option<Self::Item> {
783        // handle in-progress multi value lists first
784        if let Some((name, ref mut vals)) = self.multi_inner {
785            match vals.get(self.multi_idx) {
786                Some(val) => {
787                    self.multi_idx += 1;
788                    self.remaining -= 1;
789                    return Some((name, val));
790                }
791                None => {
792                    // no more items in value list; reset state
793                    self.multi_idx = 0;
794                    self.multi_inner = None;
795                }
796            }
797        }
798
799        let (name, value) = self.inner.next()?;
800
801        // set up new inner iter and recurse into it
802        self.multi_inner = Some((name, &value.inner));
803        self.next()
804    }
805
806    #[inline]
807    fn size_hint(&self) -> (usize, Option<usize>) {
808        (self.remaining, Some(self.remaining))
809    }
810}
811
812impl ExactSizeIterator for Iter<'_> {}
813
814impl iter::FusedIterator for Iter<'_> {}
815
816/// Iterator over drained name-value pairs.
817///
818/// Iterator items are `(Option<HeaderName>, HeaderValue)` to avoid cloning.
819#[derive(Debug)]
820pub struct Drain<'a> {
821    inner: hash_map::Drain<'a, HeaderName, Value>,
822    multi_inner: Option<(Option<HeaderName>, SmallVec<[HeaderValue; 4]>)>,
823    multi_idx: usize,
824    remaining: usize,
825}
826
827impl<'a> Drain<'a> {
828    fn new(iter: hash_map::Drain<'a, HeaderName, Value>, remaining: usize) -> Self {
829        Self {
830            inner: iter,
831            multi_inner: None,
832            multi_idx: 0,
833            remaining,
834        }
835    }
836}
837
838impl Iterator for Drain<'_> {
839    type Item = (Option<HeaderName>, HeaderValue);
840
841    fn next(&mut self) -> Option<Self::Item> {
842        // handle in-progress multi value iterators first
843        if let Some((ref mut name, ref mut vals)) = self.multi_inner {
844            if !vals.is_empty() {
845                // OPTIMIZE: array removals
846                self.remaining -= 1;
847                return Some((name.take(), vals.remove(0)));
848            } else {
849                // no more items in value iterator; reset state
850                self.multi_inner = None;
851                self.multi_idx = 0;
852            }
853        }
854
855        let (name, value) = self.inner.next()?;
856
857        // set up new inner iter and recurse into it
858        self.multi_inner = Some((Some(name), value.inner));
859        self.next()
860    }
861
862    #[inline]
863    fn size_hint(&self) -> (usize, Option<usize>) {
864        (self.remaining, Some(self.remaining))
865    }
866}
867
868impl ExactSizeIterator for Drain<'_> {}
869
870impl iter::FusedIterator for Drain<'_> {}
871
872/// Iterator over owned name-value pairs.
873///
874/// Implementation necessarily clones header names for each value.
875#[derive(Debug)]
876pub struct IntoIter {
877    inner: hash_map::IntoIter<HeaderName, Value>,
878    multi_inner: Option<(HeaderName, smallvec::IntoIter<[HeaderValue; 4]>)>,
879    remaining: usize,
880}
881
882impl IntoIter {
883    fn new(inner: hash_map::IntoIter<HeaderName, Value>, remaining: usize) -> Self {
884        Self {
885            inner,
886            multi_inner: None,
887            remaining,
888        }
889    }
890}
891
892impl Iterator for IntoIter {
893    type Item = (HeaderName, HeaderValue);
894
895    fn next(&mut self) -> Option<Self::Item> {
896        // handle in-progress multi value iterators first
897        if let Some((ref name, ref mut vals)) = self.multi_inner {
898            match vals.next() {
899                Some(val) => {
900                    self.remaining -= 1;
901                    return Some((name.clone(), val));
902                }
903                None => {
904                    // no more items in value iterator; reset state
905                    self.multi_inner = None;
906                }
907            }
908        }
909
910        let (name, value) = self.inner.next()?;
911
912        // set up new inner iter and recurse into it
913        self.multi_inner = Some((name, value.inner.into_iter()));
914        self.next()
915    }
916
917    #[inline]
918    fn size_hint(&self) -> (usize, Option<usize>) {
919        (self.remaining, Some(self.remaining))
920    }
921}
922
923impl ExactSizeIterator for IntoIter {}
924
925impl iter::FusedIterator for IntoIter {}
926
927#[cfg(test)]
928mod tests {
929    use std::iter::FusedIterator;
930
931    use http::header;
932    use static_assertions::assert_impl_all;
933
934    use super::*;
935
936    assert_impl_all!(HeaderMap: IntoIterator);
937    assert_impl_all!(Keys<'_>: Iterator, ExactSizeIterator, FusedIterator);
938    assert_impl_all!(std::slice::Iter<'_, HeaderValue>: Iterator, ExactSizeIterator, FusedIterator);
939    assert_impl_all!(Removed: Iterator, ExactSizeIterator, FusedIterator);
940    assert_impl_all!(Iter<'_>: Iterator, ExactSizeIterator, FusedIterator);
941    assert_impl_all!(IntoIter: Iterator, ExactSizeIterator, FusedIterator);
942    assert_impl_all!(Drain<'_>: Iterator, ExactSizeIterator, FusedIterator);
943
944    #[test]
945    fn create() {
946        let map = HeaderMap::new();
947        assert_eq!(map.len(), 0);
948        assert_eq!(map.capacity(), 0);
949
950        let map = HeaderMap::with_capacity(16);
951        assert_eq!(map.len(), 0);
952        assert!(map.capacity() >= 16);
953    }
954
955    #[test]
956    fn insert() {
957        let mut map = HeaderMap::new();
958
959        map.insert(header::LOCATION, HeaderValue::from_static("/test"));
960        assert_eq!(map.len(), 1);
961    }
962
963    #[test]
964    fn contains() {
965        let mut map = HeaderMap::new();
966        assert!(!map.contains_key(header::LOCATION));
967
968        map.insert(header::LOCATION, HeaderValue::from_static("/test"));
969        assert!(map.contains_key(header::LOCATION));
970        assert!(map.contains_key("Location"));
971        assert!(map.contains_key("Location".to_owned()));
972        assert!(map.contains_key("location"));
973    }
974
975    #[test]
976    fn entries_iter() {
977        let mut map = HeaderMap::new();
978
979        map.append(header::HOST, HeaderValue::from_static("duck.com"));
980        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
981        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
982
983        let mut iter = map.iter();
984        assert!(iter.next().is_some());
985        assert!(iter.next().is_some());
986        assert!(iter.next().is_some());
987        assert!(iter.next().is_none());
988
989        let pairs = map.iter().collect::<Vec<_>>();
990        assert!(pairs.contains(&(&header::HOST, &HeaderValue::from_static("duck.com"))));
991        assert!(pairs.contains(&(&header::COOKIE, &HeaderValue::from_static("one=1"))));
992        assert!(pairs.contains(&(&header::COOKIE, &HeaderValue::from_static("two=2"))));
993    }
994
995    #[test]
996    fn drain_iter() {
997        let mut map = HeaderMap::new();
998
999        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1000        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1001
1002        let mut vals = vec![];
1003        let mut iter = map.drain();
1004
1005        let (name, val) = iter.next().unwrap();
1006        assert_eq!(name, Some(header::COOKIE));
1007        vals.push(val);
1008
1009        let (name, val) = iter.next().unwrap();
1010        assert!(name.is_none());
1011        vals.push(val);
1012
1013        assert!(vals.contains(&HeaderValue::from_static("one=1")));
1014        assert!(vals.contains(&HeaderValue::from_static("two=2")));
1015
1016        assert!(iter.next().is_none());
1017        drop(iter);
1018
1019        assert!(map.is_empty());
1020    }
1021
1022    #[test]
1023    fn retain() {
1024        let mut map = HeaderMap::new();
1025
1026        map.append(header::LOCATION, HeaderValue::from_static("/test"));
1027        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1028        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1029        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1030
1031        assert_eq!(map.len(), 4);
1032
1033        // by value
1034        map.retain(|_, val| !val.as_bytes().contains(&b'/'));
1035        assert_eq!(map.len(), 3);
1036
1037        // by name
1038        map.retain(|name, _| name.as_str() != "cookie");
1039        assert_eq!(map.len(), 1);
1040
1041        // keep but mutate value
1042        map.retain(|_, val| {
1043            *val = HeaderValue::from_static("replaced");
1044            true
1045        });
1046        assert_eq!(map.len(), 1);
1047        assert_eq!(map.get("host").unwrap(), "replaced");
1048    }
1049
1050    #[test]
1051    fn retain_removes_empty_value_lists() {
1052        let mut map = HeaderMap::with_capacity(3);
1053
1054        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1055        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1056
1057        assert_eq!(map.len(), 2);
1058        assert_eq!(map.len_keys(), 1);
1059        assert_eq!(map.inner.len(), 1);
1060        assert_eq!(map.capacity(), 3);
1061
1062        // remove everything
1063        map.retain(|_n, _v| false);
1064
1065        assert_eq!(map.len(), 0);
1066        assert_eq!(map.len_keys(), 0);
1067        assert_eq!(map.inner.len(), 0);
1068        assert_eq!(map.capacity(), 3);
1069    }
1070
1071    #[test]
1072    fn entries_into_iter() {
1073        let mut map = HeaderMap::new();
1074
1075        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1076        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1077        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1078
1079        let mut iter = map.into_iter();
1080        assert!(iter.next().is_some());
1081        assert!(iter.next().is_some());
1082        assert!(iter.next().is_some());
1083        assert!(iter.next().is_none());
1084    }
1085
1086    #[test]
1087    fn iter_and_into_iter_same_order() {
1088        let mut map = HeaderMap::new();
1089
1090        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1091        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1092        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1093
1094        let mut iter = map.iter();
1095        let mut into_iter = map.clone().into_iter();
1096
1097        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1098        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1099        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1100        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1101    }
1102
1103    #[test]
1104    fn get_all_and_remove_same_order() {
1105        let mut map = HeaderMap::new();
1106
1107        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1108        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1109
1110        let mut vals = map.get_all(header::COOKIE);
1111        let mut removed = map.clone().remove(header::COOKIE);
1112
1113        assert_eq!(vals.next(), removed.next().as_ref());
1114        assert_eq!(vals.next(), removed.next().as_ref());
1115        assert_eq!(vals.next(), removed.next().as_ref());
1116    }
1117
1118    #[test]
1119    fn get_all_iteration_order_matches_insertion_order() {
1120        let mut map = HeaderMap::new();
1121
1122        let mut vals = map.get_all(header::COOKIE);
1123        assert!(vals.next().is_none());
1124
1125        map.append(header::COOKIE, HeaderValue::from_static("1"));
1126        let mut vals = map.get_all(header::COOKIE);
1127        assert_eq!(vals.next().unwrap().as_bytes(), b"1");
1128        assert!(vals.next().is_none());
1129
1130        map.append(header::COOKIE, HeaderValue::from_static("2"));
1131        let mut vals = map.get_all(header::COOKIE);
1132        assert_eq!(vals.next().unwrap().as_bytes(), b"1");
1133        assert_eq!(vals.next().unwrap().as_bytes(), b"2");
1134        assert!(vals.next().is_none());
1135
1136        map.append(header::COOKIE, HeaderValue::from_static("3"));
1137        map.append(header::COOKIE, HeaderValue::from_static("4"));
1138        map.append(header::COOKIE, HeaderValue::from_static("5"));
1139        let mut vals = map.get_all(header::COOKIE);
1140        assert_eq!(vals.next().unwrap().as_bytes(), b"1");
1141        assert_eq!(vals.next().unwrap().as_bytes(), b"2");
1142        assert_eq!(vals.next().unwrap().as_bytes(), b"3");
1143        assert_eq!(vals.next().unwrap().as_bytes(), b"4");
1144        assert_eq!(vals.next().unwrap().as_bytes(), b"5");
1145        assert!(vals.next().is_none());
1146
1147        let _ = map.insert(header::COOKIE, HeaderValue::from_static("6"));
1148        let mut vals = map.get_all(header::COOKIE);
1149        assert_eq!(vals.next().unwrap().as_bytes(), b"6");
1150        assert!(vals.next().is_none());
1151
1152        let _ = map.insert(header::COOKIE, HeaderValue::from_static("7"));
1153        let _ = map.insert(header::COOKIE, HeaderValue::from_static("8"));
1154        let mut vals = map.get_all(header::COOKIE);
1155        assert_eq!(vals.next().unwrap().as_bytes(), b"8");
1156        assert!(vals.next().is_none());
1157
1158        map.append(header::COOKIE, HeaderValue::from_static("9"));
1159        let mut vals = map.get_all(header::COOKIE);
1160        assert_eq!(vals.next().unwrap().as_bytes(), b"8");
1161        assert_eq!(vals.next().unwrap().as_bytes(), b"9");
1162        assert!(vals.next().is_none());
1163
1164        // check for fused-ness
1165        assert!(vals.next().is_none());
1166    }
1167
1168    #[test]
1169    fn iter_len_counts_values() {
1170        let mut map = HeaderMap::new();
1171        map.append(header::SET_COOKIE, HeaderValue::from_static("a=1"));
1172        map.append(header::SET_COOKIE, HeaderValue::from_static("b=2"));
1173        map.append(header::SET_COOKIE, HeaderValue::from_static("c=3"));
1174
1175        assert_eq!(map.iter().count(), 3);
1176        assert_eq!(map.iter().len(), 3);
1177    }
1178
1179    #[test]
1180    fn into_iter_len_counts_values() {
1181        let mut map = HeaderMap::new();
1182        map.append(header::SET_COOKIE, HeaderValue::from_static("a=1"));
1183        map.append(header::SET_COOKIE, HeaderValue::from_static("b=2"));
1184        map.append(header::SET_COOKIE, HeaderValue::from_static("c=3"));
1185
1186        assert_eq!(map.clone().into_iter().count(), 3);
1187        assert_eq!(map.into_iter().len(), 3);
1188    }
1189
1190    #[test]
1191    fn drain_len_counts_values() {
1192        let mut map = HeaderMap::new();
1193        map.append(header::SET_COOKIE, HeaderValue::from_static("a=1"));
1194        map.append(header::SET_COOKIE, HeaderValue::from_static("b=2"));
1195        map.append(header::SET_COOKIE, HeaderValue::from_static("c=3"));
1196
1197        let mut drained = map.clone();
1198        assert_eq!(map.drain().count(), 3);
1199        assert_eq!(drained.drain().len(), 3);
1200    }
1201
1202    fn owned_pair<'a>((name, val): (&'a HeaderName, &'a HeaderValue)) -> (HeaderName, HeaderValue) {
1203        (name.clone(), val.clone())
1204    }
1205}