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}