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())
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        Drain::new(self.inner.drain())
630    }
631}
632
633/// Note that this implementation will clone a [HeaderName] for each value. Consider using
634/// [`drain`](Self::drain) to control header name cloning.
635impl IntoIterator for HeaderMap {
636    type Item = (HeaderName, HeaderValue);
637    type IntoIter = IntoIter;
638
639    #[inline]
640    fn into_iter(self) -> Self::IntoIter {
641        IntoIter::new(self.inner.into_iter())
642    }
643}
644
645impl<'a> IntoIterator for &'a HeaderMap {
646    type Item = (&'a HeaderName, &'a HeaderValue);
647    type IntoIter = Iter<'a>;
648
649    #[inline]
650    fn into_iter(self) -> Self::IntoIter {
651        Iter::new(self.inner.iter())
652    }
653}
654
655impl FromIterator<(HeaderName, HeaderValue)> for HeaderMap {
656    fn from_iter<T: IntoIterator<Item = (HeaderName, HeaderValue)>>(iter: T) -> Self {
657        iter.into_iter()
658            .fold(Self::new(), |mut map, (name, value)| {
659                map.append(name, value);
660                map
661            })
662    }
663}
664
665/// Convert a `http::HeaderMap` to our `HeaderMap`.
666impl From<http::HeaderMap> for HeaderMap {
667    fn from(mut map: http::HeaderMap) -> Self {
668        Self::from_drain(map.drain())
669    }
670}
671
672/// Convert our `HeaderMap` to a `http::HeaderMap`.
673impl From<HeaderMap> for http::HeaderMap {
674    fn from(map: HeaderMap) -> Self {
675        Self::from_iter(map)
676    }
677}
678
679/// Convert our `&HeaderMap` to a `http::HeaderMap`.
680impl From<&HeaderMap> for http::HeaderMap {
681    fn from(map: &HeaderMap) -> Self {
682        map.to_owned().into()
683    }
684}
685
686/// Iterator over removed, owned values with the same associated name.
687///
688/// Returned from methods that remove or replace items. See [`HeaderMap::insert`]
689/// and [`HeaderMap::remove`].
690#[derive(Debug)]
691pub struct Removed {
692    inner: Option<smallvec::IntoIter<[HeaderValue; 4]>>,
693}
694
695impl Removed {
696    fn new(value: Option<Value>) -> Self {
697        let inner = value.map(|value| value.inner.into_iter());
698        Self { inner }
699    }
700
701    /// Returns true if iterator contains no elements, without consuming it.
702    ///
703    /// If called immediately after [`HeaderMap::insert`] or [`HeaderMap::remove`], it will indicate
704    /// whether any items were actually replaced or removed, respectively.
705    pub fn is_empty(&self) -> bool {
706        match self.inner {
707            // size hint lower bound of smallvec is the correct length
708            Some(ref iter) => iter.size_hint().0 == 0,
709            None => true,
710        }
711    }
712}
713
714impl Iterator for Removed {
715    type Item = HeaderValue;
716
717    #[inline]
718    fn next(&mut self) -> Option<Self::Item> {
719        self.inner.as_mut()?.next()
720    }
721
722    #[inline]
723    fn size_hint(&self) -> (usize, Option<usize>) {
724        match self.inner {
725            Some(ref iter) => iter.size_hint(),
726            None => (0, None),
727        }
728    }
729}
730
731impl ExactSizeIterator for Removed {}
732
733impl iter::FusedIterator for Removed {}
734
735/// Iterator over all names in the map.
736#[derive(Debug)]
737pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);
738
739impl<'a> Iterator for Keys<'a> {
740    type Item = &'a HeaderName;
741
742    #[inline]
743    fn next(&mut self) -> Option<Self::Item> {
744        self.0.next()
745    }
746
747    #[inline]
748    fn size_hint(&self) -> (usize, Option<usize>) {
749        self.0.size_hint()
750    }
751}
752
753impl ExactSizeIterator for Keys<'_> {}
754
755impl iter::FusedIterator for Keys<'_> {}
756
757/// Iterator over borrowed name-value pairs.
758#[derive(Debug)]
759pub struct Iter<'a> {
760    inner: hash_map::Iter<'a, HeaderName, Value>,
761    multi_inner: Option<(&'a HeaderName, &'a SmallVec<[HeaderValue; 4]>)>,
762    multi_idx: usize,
763}
764
765impl<'a> Iter<'a> {
766    fn new(iter: hash_map::Iter<'a, HeaderName, Value>) -> Self {
767        Self {
768            inner: iter,
769            multi_idx: 0,
770            multi_inner: None,
771        }
772    }
773}
774
775impl<'a> Iterator for Iter<'a> {
776    type Item = (&'a HeaderName, &'a HeaderValue);
777
778    fn next(&mut self) -> Option<Self::Item> {
779        // handle in-progress multi value lists first
780        if let Some((name, ref mut vals)) = self.multi_inner {
781            match vals.get(self.multi_idx) {
782                Some(val) => {
783                    self.multi_idx += 1;
784                    return Some((name, val));
785                }
786                None => {
787                    // no more items in value list; reset state
788                    self.multi_idx = 0;
789                    self.multi_inner = None;
790                }
791            }
792        }
793
794        let (name, value) = self.inner.next()?;
795
796        // set up new inner iter and recurse into it
797        self.multi_inner = Some((name, &value.inner));
798        self.next()
799    }
800
801    #[inline]
802    fn size_hint(&self) -> (usize, Option<usize>) {
803        // take inner lower bound
804        // make no attempt at an upper bound
805        (self.inner.size_hint().0, None)
806    }
807}
808
809impl ExactSizeIterator for Iter<'_> {}
810
811impl iter::FusedIterator for Iter<'_> {}
812
813/// Iterator over drained name-value pairs.
814///
815/// Iterator items are `(Option<HeaderName>, HeaderValue)` to avoid cloning.
816#[derive(Debug)]
817pub struct Drain<'a> {
818    inner: hash_map::Drain<'a, HeaderName, Value>,
819    multi_inner: Option<(Option<HeaderName>, SmallVec<[HeaderValue; 4]>)>,
820    multi_idx: usize,
821}
822
823impl<'a> Drain<'a> {
824    fn new(iter: hash_map::Drain<'a, HeaderName, Value>) -> Self {
825        Self {
826            inner: iter,
827            multi_inner: None,
828            multi_idx: 0,
829        }
830    }
831}
832
833impl Iterator for Drain<'_> {
834    type Item = (Option<HeaderName>, HeaderValue);
835
836    fn next(&mut self) -> Option<Self::Item> {
837        // handle in-progress multi value iterators first
838        if let Some((ref mut name, ref mut vals)) = self.multi_inner {
839            if !vals.is_empty() {
840                // OPTIMIZE: array removals
841                return Some((name.take(), vals.remove(0)));
842            } else {
843                // no more items in value iterator; reset state
844                self.multi_inner = None;
845                self.multi_idx = 0;
846            }
847        }
848
849        let (name, value) = self.inner.next()?;
850
851        // set up new inner iter and recurse into it
852        self.multi_inner = Some((Some(name), value.inner));
853        self.next()
854    }
855
856    #[inline]
857    fn size_hint(&self) -> (usize, Option<usize>) {
858        // take inner lower bound
859        // make no attempt at an upper bound
860        (self.inner.size_hint().0, None)
861    }
862}
863
864impl ExactSizeIterator for Drain<'_> {}
865
866impl iter::FusedIterator for Drain<'_> {}
867
868/// Iterator over owned name-value pairs.
869///
870/// Implementation necessarily clones header names for each value.
871#[derive(Debug)]
872pub struct IntoIter {
873    inner: hash_map::IntoIter<HeaderName, Value>,
874    multi_inner: Option<(HeaderName, smallvec::IntoIter<[HeaderValue; 4]>)>,
875}
876
877impl IntoIter {
878    fn new(inner: hash_map::IntoIter<HeaderName, Value>) -> Self {
879        Self {
880            inner,
881            multi_inner: None,
882        }
883    }
884}
885
886impl Iterator for IntoIter {
887    type Item = (HeaderName, HeaderValue);
888
889    fn next(&mut self) -> Option<Self::Item> {
890        // handle in-progress multi value iterators first
891        if let Some((ref name, ref mut vals)) = self.multi_inner {
892            match vals.next() {
893                Some(val) => {
894                    return Some((name.clone(), val));
895                }
896                None => {
897                    // no more items in value iterator; reset state
898                    self.multi_inner = None;
899                }
900            }
901        }
902
903        let (name, value) = self.inner.next()?;
904
905        // set up new inner iter and recurse into it
906        self.multi_inner = Some((name, value.inner.into_iter()));
907        self.next()
908    }
909
910    #[inline]
911    fn size_hint(&self) -> (usize, Option<usize>) {
912        // take inner lower bound
913        // make no attempt at an upper bound
914        (self.inner.size_hint().0, None)
915    }
916}
917
918impl ExactSizeIterator for IntoIter {}
919
920impl iter::FusedIterator for IntoIter {}
921
922#[cfg(test)]
923mod tests {
924    use std::iter::FusedIterator;
925
926    use http::header;
927    use static_assertions::assert_impl_all;
928
929    use super::*;
930
931    assert_impl_all!(HeaderMap: IntoIterator);
932    assert_impl_all!(Keys<'_>: Iterator, ExactSizeIterator, FusedIterator);
933    assert_impl_all!(std::slice::Iter<'_, HeaderValue>: Iterator, ExactSizeIterator, FusedIterator);
934    assert_impl_all!(Removed: Iterator, ExactSizeIterator, FusedIterator);
935    assert_impl_all!(Iter<'_>: Iterator, ExactSizeIterator, FusedIterator);
936    assert_impl_all!(IntoIter: Iterator, ExactSizeIterator, FusedIterator);
937    assert_impl_all!(Drain<'_>: Iterator, ExactSizeIterator, FusedIterator);
938
939    #[test]
940    fn create() {
941        let map = HeaderMap::new();
942        assert_eq!(map.len(), 0);
943        assert_eq!(map.capacity(), 0);
944
945        let map = HeaderMap::with_capacity(16);
946        assert_eq!(map.len(), 0);
947        assert!(map.capacity() >= 16);
948    }
949
950    #[test]
951    fn insert() {
952        let mut map = HeaderMap::new();
953
954        map.insert(header::LOCATION, HeaderValue::from_static("/test"));
955        assert_eq!(map.len(), 1);
956    }
957
958    #[test]
959    fn contains() {
960        let mut map = HeaderMap::new();
961        assert!(!map.contains_key(header::LOCATION));
962
963        map.insert(header::LOCATION, HeaderValue::from_static("/test"));
964        assert!(map.contains_key(header::LOCATION));
965        assert!(map.contains_key("Location"));
966        assert!(map.contains_key("Location".to_owned()));
967        assert!(map.contains_key("location"));
968    }
969
970    #[test]
971    fn entries_iter() {
972        let mut map = HeaderMap::new();
973
974        map.append(header::HOST, HeaderValue::from_static("duck.com"));
975        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
976        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
977
978        let mut iter = map.iter();
979        assert!(iter.next().is_some());
980        assert!(iter.next().is_some());
981        assert!(iter.next().is_some());
982        assert!(iter.next().is_none());
983
984        let pairs = map.iter().collect::<Vec<_>>();
985        assert!(pairs.contains(&(&header::HOST, &HeaderValue::from_static("duck.com"))));
986        assert!(pairs.contains(&(&header::COOKIE, &HeaderValue::from_static("one=1"))));
987        assert!(pairs.contains(&(&header::COOKIE, &HeaderValue::from_static("two=2"))));
988    }
989
990    #[test]
991    fn drain_iter() {
992        let mut map = HeaderMap::new();
993
994        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
995        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
996
997        let mut vals = vec![];
998        let mut iter = map.drain();
999
1000        let (name, val) = iter.next().unwrap();
1001        assert_eq!(name, Some(header::COOKIE));
1002        vals.push(val);
1003
1004        let (name, val) = iter.next().unwrap();
1005        assert!(name.is_none());
1006        vals.push(val);
1007
1008        assert!(vals.contains(&HeaderValue::from_static("one=1")));
1009        assert!(vals.contains(&HeaderValue::from_static("two=2")));
1010
1011        assert!(iter.next().is_none());
1012        drop(iter);
1013
1014        assert!(map.is_empty());
1015    }
1016
1017    #[test]
1018    fn retain() {
1019        let mut map = HeaderMap::new();
1020
1021        map.append(header::LOCATION, HeaderValue::from_static("/test"));
1022        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1023        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1024        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1025
1026        assert_eq!(map.len(), 4);
1027
1028        // by value
1029        map.retain(|_, val| !val.as_bytes().contains(&b'/'));
1030        assert_eq!(map.len(), 3);
1031
1032        // by name
1033        map.retain(|name, _| name.as_str() != "cookie");
1034        assert_eq!(map.len(), 1);
1035
1036        // keep but mutate value
1037        map.retain(|_, val| {
1038            *val = HeaderValue::from_static("replaced");
1039            true
1040        });
1041        assert_eq!(map.len(), 1);
1042        assert_eq!(map.get("host").unwrap(), "replaced");
1043    }
1044
1045    #[test]
1046    fn retain_removes_empty_value_lists() {
1047        let mut map = HeaderMap::with_capacity(3);
1048
1049        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1050        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1051
1052        assert_eq!(map.len(), 2);
1053        assert_eq!(map.len_keys(), 1);
1054        assert_eq!(map.inner.len(), 1);
1055        assert_eq!(map.capacity(), 3);
1056
1057        // remove everything
1058        map.retain(|_n, _v| false);
1059
1060        assert_eq!(map.len(), 0);
1061        assert_eq!(map.len_keys(), 0);
1062        assert_eq!(map.inner.len(), 0);
1063        assert_eq!(map.capacity(), 3);
1064    }
1065
1066    #[test]
1067    fn entries_into_iter() {
1068        let mut map = HeaderMap::new();
1069
1070        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1071        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1072        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1073
1074        let mut iter = map.into_iter();
1075        assert!(iter.next().is_some());
1076        assert!(iter.next().is_some());
1077        assert!(iter.next().is_some());
1078        assert!(iter.next().is_none());
1079    }
1080
1081    #[test]
1082    fn iter_and_into_iter_same_order() {
1083        let mut map = HeaderMap::new();
1084
1085        map.append(header::HOST, HeaderValue::from_static("duck.com"));
1086        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1087        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1088
1089        let mut iter = map.iter();
1090        let mut into_iter = map.clone().into_iter();
1091
1092        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1093        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1094        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1095        assert_eq!(iter.next().map(owned_pair), into_iter.next());
1096    }
1097
1098    #[test]
1099    fn get_all_and_remove_same_order() {
1100        let mut map = HeaderMap::new();
1101
1102        map.append(header::COOKIE, HeaderValue::from_static("one=1"));
1103        map.append(header::COOKIE, HeaderValue::from_static("two=2"));
1104
1105        let mut vals = map.get_all(header::COOKIE);
1106        let mut removed = map.clone().remove(header::COOKIE);
1107
1108        assert_eq!(vals.next(), removed.next().as_ref());
1109        assert_eq!(vals.next(), removed.next().as_ref());
1110        assert_eq!(vals.next(), removed.next().as_ref());
1111    }
1112
1113    #[test]
1114    fn get_all_iteration_order_matches_insertion_order() {
1115        let mut map = HeaderMap::new();
1116
1117        let mut vals = map.get_all(header::COOKIE);
1118        assert!(vals.next().is_none());
1119
1120        map.append(header::COOKIE, HeaderValue::from_static("1"));
1121        let mut vals = map.get_all(header::COOKIE);
1122        assert_eq!(vals.next().unwrap().as_bytes(), b"1");
1123        assert!(vals.next().is_none());
1124
1125        map.append(header::COOKIE, HeaderValue::from_static("2"));
1126        let mut vals = map.get_all(header::COOKIE);
1127        assert_eq!(vals.next().unwrap().as_bytes(), b"1");
1128        assert_eq!(vals.next().unwrap().as_bytes(), b"2");
1129        assert!(vals.next().is_none());
1130
1131        map.append(header::COOKIE, HeaderValue::from_static("3"));
1132        map.append(header::COOKIE, HeaderValue::from_static("4"));
1133        map.append(header::COOKIE, HeaderValue::from_static("5"));
1134        let mut vals = map.get_all(header::COOKIE);
1135        assert_eq!(vals.next().unwrap().as_bytes(), b"1");
1136        assert_eq!(vals.next().unwrap().as_bytes(), b"2");
1137        assert_eq!(vals.next().unwrap().as_bytes(), b"3");
1138        assert_eq!(vals.next().unwrap().as_bytes(), b"4");
1139        assert_eq!(vals.next().unwrap().as_bytes(), b"5");
1140        assert!(vals.next().is_none());
1141
1142        let _ = map.insert(header::COOKIE, HeaderValue::from_static("6"));
1143        let mut vals = map.get_all(header::COOKIE);
1144        assert_eq!(vals.next().unwrap().as_bytes(), b"6");
1145        assert!(vals.next().is_none());
1146
1147        let _ = map.insert(header::COOKIE, HeaderValue::from_static("7"));
1148        let _ = map.insert(header::COOKIE, HeaderValue::from_static("8"));
1149        let mut vals = map.get_all(header::COOKIE);
1150        assert_eq!(vals.next().unwrap().as_bytes(), b"8");
1151        assert!(vals.next().is_none());
1152
1153        map.append(header::COOKIE, HeaderValue::from_static("9"));
1154        let mut vals = map.get_all(header::COOKIE);
1155        assert_eq!(vals.next().unwrap().as_bytes(), b"8");
1156        assert_eq!(vals.next().unwrap().as_bytes(), b"9");
1157        assert!(vals.next().is_none());
1158
1159        // check for fused-ness
1160        assert!(vals.next().is_none());
1161    }
1162
1163    fn owned_pair<'a>((name, val): (&'a HeaderName, &'a HeaderValue)) -> (HeaderName, HeaderValue) {
1164        (name.clone(), val.clone())
1165    }
1166}