Skip to main content

ntex_http/
map.rs

1use std::collections::{self, VecDeque, hash_map, hash_map::Entry};
2use std::fmt;
3
4use foldhash::fast::RandomState;
5
6use crate::{HeaderName, HeaderValue};
7
8type HashMap<K, V> = collections::HashMap<K, V, RandomState>;
9
10/// A value containing one of two possible types.
11#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
12pub enum Either<A, B> {
13    /// First variant.
14    Left(A),
15    /// Second variant.
16    Right(B),
17}
18
19/// A multimap of HTTP header names to values.
20///
21/// Each header name may have one or more values. Methods such as [`get`](Self::get)
22/// return the first value; use [`get_all`](Self::get_all) to iterate over every
23/// value associated with a name.
24#[derive(Clone, PartialEq, Eq)]
25pub struct HeaderMap {
26    pub(crate) inner: HashMap<HeaderName, Value>,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub enum Value {
31    One(HeaderValue),
32    Multi(VecDeque<HeaderValue>),
33}
34
35impl Value {
36    fn get(&self) -> &HeaderValue {
37        match self {
38            Value::One(val) => val,
39            Value::Multi(val) => &val[0],
40        }
41    }
42
43    fn get_mut(&mut self) -> &mut HeaderValue {
44        match self {
45            Value::One(val) => val,
46            Value::Multi(val) => &mut val[0],
47        }
48    }
49
50    pub(crate) fn append(&mut self, val: HeaderValue) {
51        *self = match std::mem::replace(self, Value::Multi(VecDeque::new())) {
52            Value::One(prev_val) => Value::Multi(VecDeque::from([prev_val, val])),
53            Value::Multi(mut vec) => {
54                vec.push_back(val);
55                Value::Multi(vec)
56            }
57        };
58    }
59}
60
61#[derive(Debug)]
62pub struct ValueIntoIter {
63    value: Value,
64}
65
66impl Iterator for ValueIntoIter {
67    type Item = HeaderValue;
68
69    fn next(&mut self) -> Option<Self::Item> {
70        match std::mem::replace(&mut self.value, Value::Multi(VecDeque::new())) {
71            Value::One(val) => Some(val),
72            Value::Multi(mut vec) => {
73                let val = vec.pop_front();
74                self.value = Value::Multi(vec);
75                val
76            }
77        }
78    }
79
80    fn size_hint(&self) -> (usize, Option<usize>) {
81        match self.value {
82            Value::One(_) => (1, Some(1)),
83            Value::Multi(ref v) => v.iter().size_hint(),
84        }
85    }
86}
87
88impl IntoIterator for Value {
89    type Item = HeaderValue;
90    type IntoIter = ValueIntoIter;
91
92    #[inline]
93    fn into_iter(self) -> Self::IntoIter {
94        ValueIntoIter { value: self }
95    }
96}
97
98impl Extend<HeaderValue> for Value {
99    #[inline]
100    fn extend<T>(&mut self, iter: T)
101    where
102        T: IntoIterator<Item = HeaderValue>,
103    {
104        for h in iter {
105            self.append(h);
106        }
107    }
108}
109
110impl From<HeaderValue> for Value {
111    #[inline]
112    fn from(hdr: HeaderValue) -> Value {
113        Value::One(hdr)
114    }
115}
116
117impl<'a> From<&'a HeaderValue> for Value {
118    #[inline]
119    fn from(hdr: &'a HeaderValue) -> Value {
120        Value::One(hdr.clone())
121    }
122}
123
124impl Default for HeaderMap {
125    #[inline]
126    fn default() -> Self {
127        Self::new()
128    }
129}
130
131impl HeaderMap {
132    /// Creates an empty `HeaderMap`.
133    ///
134    /// The map will be created without any capacity. This function will not
135    /// allocate.
136    pub fn new() -> Self {
137        HeaderMap {
138            inner: HashMap::default(),
139        }
140    }
141
142    /// Creates an empty `HeaderMap` with the specified capacity.
143    ///
144    /// The returned map will allocate internal storage in order to hold about
145    /// `capacity` elements without reallocating. However, this is a "best
146    /// effort" as there are usage patterns that could cause additional
147    /// allocations before `capacity` headers are stored in the map.
148    ///
149    /// More capacity than requested may be allocated.
150    pub fn with_capacity(capacity: usize) -> HeaderMap {
151        HeaderMap {
152            inner: HashMap::with_capacity_and_hasher(capacity, RandomState::default()),
153        }
154    }
155
156    /// Returns the number of keys stored in the map.
157    ///
158    /// This counts distinct header names, not the total number of values.
159    pub fn len(&self) -> usize {
160        self.inner.len()
161    }
162
163    /// Returns `true` if the map contains no headers.
164    pub fn is_empty(&self) -> bool {
165        self.inner.len() == 0
166    }
167
168    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
169    /// for reuse.
170    pub fn clear(&mut self) {
171        self.inner.clear();
172    }
173
174    /// Returns the number of headers the map can hold without reallocating.
175    ///
176    /// This number is an approximation as certain usage patterns could cause
177    /// additional allocations before the returned capacity is filled.
178    pub fn capacity(&self) -> usize {
179        self.inner.capacity()
180    }
181
182    /// Reserves capacity for at least `additional` more headers to be inserted
183    /// into the `HeaderMap`.
184    ///
185    /// The header map may reserve more space to avoid frequent reallocations.
186    /// Like with `with_capacity`, this will be a "best effort" to avoid
187    /// allocations until `additional` more headers are inserted. Certain usage
188    /// patterns could cause additional allocations before the number is
189    /// reached.
190    pub fn reserve(&mut self, additional: usize) {
191        self.inner.reserve(additional);
192    }
193
194    /// Returns a reference to the value associated with the key.
195    ///
196    /// If there are multiple values associated with the key, then the first one
197    /// is returned. Use `get_all` to get all values associated with a given
198    /// key. Returns `None` if there are no values associated with the key.
199    pub fn get<N: AsName>(&self, name: N) -> Option<&HeaderValue> {
200        self.get2(name).map(Value::get)
201    }
202
203    fn get2<N: AsName>(&self, name: N) -> Option<&Value> {
204        match name.as_name() {
205            Either::Left(name) => self.inner.get(name),
206            Either::Right(s) => {
207                if let Ok(name) = HeaderName::try_from(s) {
208                    self.inner.get(&name)
209                } else {
210                    None
211                }
212            }
213        }
214    }
215
216    /// Returns a view of all values associated with a key.
217    ///
218    /// The returned view does not incur any allocations and allows iterating
219    /// the values associated with the key. The iterator is empty if there are
220    /// no values associated with the key.
221    pub fn get_all<N: AsName>(&self, name: N) -> GetAll<'_> {
222        GetAll {
223            idx: 0,
224            item: self.get2(name),
225        }
226    }
227
228    /// Returns a mutable reference to the value associated with the key.
229    ///
230    /// If there are multiple values associated with the key, then the first one
231    /// is returned. Use `get_all` to get all values associated with a given
232    /// key. Returns `None` if there are no values associated with the key.
233    pub fn get_mut<N: AsName>(&mut self, name: N) -> Option<&mut HeaderValue> {
234        match name.as_name() {
235            Either::Left(name) => self.inner.get_mut(name).map(Value::get_mut),
236            Either::Right(s) => {
237                if let Ok(name) = HeaderName::try_from(s) {
238                    self.inner.get_mut(&name).map(Value::get_mut)
239                } else {
240                    None
241                }
242            }
243        }
244    }
245
246    /// Returns `true` if the map contains a value for the specified key.
247    pub fn contains_key<N: AsName>(&self, key: N) -> bool {
248        match key.as_name() {
249            Either::Left(name) => self.inner.contains_key(name),
250            Either::Right(s) => {
251                if let Ok(name) = HeaderName::try_from(s) {
252                    self.inner.contains_key(&name)
253                } else {
254                    false
255                }
256            }
257        }
258    }
259
260    /// An iterator visiting all key-value pairs.
261    ///
262    /// The iteration order is arbitrary and may vary between maps. Each key is
263    /// yielded once per associated value.
264    pub fn iter(&self) -> Iter<'_> {
265        Iter::new(self.inner.iter())
266    }
267
268    #[doc(hidden)]
269    pub fn iter_inner(&self) -> hash_map::Iter<'_, HeaderName, Value> {
270        self.inner.iter()
271    }
272
273    /// An iterator visiting all keys.
274    ///
275    /// The iteration order is arbitrary and may vary between maps. Each key is
276    /// yielded only once, even if it has multiple associated values.
277    pub fn keys(&self) -> Keys<'_> {
278        Keys(self.inner.keys())
279    }
280
281    /// Inserts a key-value pair into the map.
282    ///
283    /// The new value replaces all values previously associated with the key.
284    ///
285    /// The key is not updated, though; this matters for types that can be `==`
286    /// without being identical.
287    pub fn insert(&mut self, key: HeaderName, val: HeaderValue) {
288        let _ = self.inner.insert(key, Value::One(val));
289    }
290
291    /// Inserts a key-value pair into the map.
292    ///
293    /// The value is appended after any values already associated with the key.
294    /// The stored key itself is not replaced when an equivalent key exists.
295    pub fn append(&mut self, key: HeaderName, value: HeaderValue) {
296        match self.inner.entry(key) {
297            Entry::Occupied(mut entry) => entry.get_mut().append(value),
298            Entry::Vacant(entry) => {
299                entry.insert(Value::One(value));
300            }
301        }
302    }
303
304    /// Removes all headers for a particular header name from the map.
305    pub fn remove<N: AsName>(&mut self, key: N) {
306        match key.as_name() {
307            Either::Left(name) => {
308                let _ = self.inner.remove(name);
309            }
310            Either::Right(s) => {
311                if let Ok(name) = HeaderName::try_from(s) {
312                    let _ = self.inner.remove(&name);
313                }
314            }
315        }
316    }
317}
318
319#[doc(hidden)]
320pub trait AsName {
321    fn as_name(&self) -> Either<&HeaderName, &str>;
322}
323
324impl AsName for HeaderName {
325    fn as_name(&self) -> Either<&HeaderName, &str> {
326        Either::Left(self)
327    }
328}
329
330impl AsName for &HeaderName {
331    fn as_name(&self) -> Either<&HeaderName, &str> {
332        Either::Left(self)
333    }
334}
335
336impl AsName for &str {
337    fn as_name(&self) -> Either<&HeaderName, &str> {
338        Either::Right(self)
339    }
340}
341
342impl AsName for String {
343    fn as_name(&self) -> Either<&HeaderName, &str> {
344        Either::Right(self.as_str())
345    }
346}
347
348impl AsName for &String {
349    fn as_name(&self) -> Either<&HeaderName, &str> {
350        Either::Right(self.as_str())
351    }
352}
353
354#[derive(Debug)]
355pub struct GetAll<'a> {
356    idx: usize,
357    item: Option<&'a Value>,
358}
359
360impl<'a> Iterator for GetAll<'a> {
361    type Item = &'a HeaderValue;
362
363    #[inline]
364    fn next(&mut self) -> Option<&'a HeaderValue> {
365        if let Some(ref val) = self.item {
366            match val {
367                Value::One(val) => {
368                    self.item.take();
369                    Some(val)
370                }
371                Value::Multi(vec) => {
372                    if self.idx < vec.len() {
373                        let item = Some(&vec[self.idx]);
374                        self.idx += 1;
375                        item
376                    } else {
377                        self.item.take();
378                        None
379                    }
380                }
381            }
382        } else {
383            None
384        }
385    }
386}
387
388#[derive(Debug)]
389pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);
390
391impl<'a> Iterator for Keys<'a> {
392    type Item = &'a HeaderName;
393
394    #[inline]
395    fn next(&mut self) -> Option<&'a HeaderName> {
396        self.0.next()
397    }
398}
399
400impl<'a> IntoIterator for &'a HeaderMap {
401    type Item = (&'a HeaderName, &'a HeaderValue);
402    type IntoIter = Iter<'a>;
403
404    fn into_iter(self) -> Self::IntoIter {
405        self.iter()
406    }
407}
408
409#[derive(Debug)]
410pub struct Iter<'a> {
411    idx: usize,
412    current: Option<(&'a HeaderName, &'a VecDeque<HeaderValue>)>,
413    inner: hash_map::Iter<'a, HeaderName, Value>,
414}
415
416impl<'a> Iter<'a> {
417    fn new(inner: hash_map::Iter<'a, HeaderName, Value>) -> Self {
418        Self {
419            inner,
420            idx: 0,
421            current: None,
422        }
423    }
424}
425
426impl<'a> Iterator for Iter<'a> {
427    type Item = (&'a HeaderName, &'a HeaderValue);
428
429    #[inline]
430    fn next(&mut self) -> Option<(&'a HeaderName, &'a HeaderValue)> {
431        if let Some(ref mut item) = self.current {
432            if self.idx < item.1.len() {
433                let item = (item.0, &item.1[self.idx]);
434                self.idx += 1;
435                return Some(item);
436            }
437            self.idx = 0;
438            self.current.take();
439        }
440        if let Some(item) = self.inner.next() {
441            match item.1 {
442                Value::One(value) => Some((item.0, value)),
443                Value::Multi(vec) => {
444                    self.current = Some((item.0, vec));
445                    self.next()
446                }
447            }
448        } else {
449            None
450        }
451    }
452}
453
454impl fmt::Debug for HeaderMap {
455    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456        let mut f = f.debug_map();
457
458        for (key, val) in &self.inner {
459            match val {
460                Value::One(val) => {
461                    let _ = f.entry(&key, &val);
462                }
463                Value::Multi(val) => {
464                    for v in val {
465                        f.entry(&key, &v);
466                    }
467                }
468            }
469        }
470        f.finish()
471    }
472}
473
474#[cfg(test)]
475mod tests {
476    use super::*;
477    use crate::header::{ACCEPT_ENCODING, CONTENT_TYPE};
478
479    #[test]
480    #[allow(clippy::needless_borrow, clippy::needless_borrows_for_generic_args)]
481    fn test_basics() {
482        let m = HeaderMap::default();
483        assert!(m.is_empty());
484        let mut m = HeaderMap::with_capacity(10);
485        assert!(m.is_empty());
486        assert!(m.capacity() >= 10);
487        m.reserve(20);
488        assert!(m.capacity() >= 20);
489
490        m.insert(CONTENT_TYPE, HeaderValue::from_static("text"));
491        assert!(m.contains_key(CONTENT_TYPE));
492        assert!(m.contains_key("content-type"));
493        assert!(m.contains_key("content-type".to_string()));
494        assert!(m.contains_key(&("content-type".to_string())));
495        assert_eq!(
496            *m.get_mut("content-type").unwrap(),
497            HeaderValue::from_static("text")
498        );
499        assert_eq!(
500            *m.get_mut(CONTENT_TYPE).unwrap(),
501            HeaderValue::from_static("text")
502        );
503        assert!(format!("{m:?}").contains("content-type"));
504
505        assert!(m.keys().any(|x| x == CONTENT_TYPE));
506        m.remove("content-type");
507        assert!(m.is_empty());
508    }
509
510    #[test]
511    fn test_append() {
512        let mut map = HeaderMap::new();
513
514        map.append(ACCEPT_ENCODING, HeaderValue::from_static("gzip"));
515        assert_eq!(
516            map.get_all(ACCEPT_ENCODING).collect::<Vec<_>>(),
517            vec![&HeaderValue::from_static("gzip"),]
518        );
519
520        map.append(ACCEPT_ENCODING, HeaderValue::from_static("br"));
521        map.append(ACCEPT_ENCODING, HeaderValue::from_static("deflate"));
522        assert_eq!(
523            map.get_all(ACCEPT_ENCODING).collect::<Vec<_>>(),
524            vec![
525                &HeaderValue::from_static("gzip"),
526                &HeaderValue::from_static("br"),
527                &HeaderValue::from_static("deflate"),
528            ]
529        );
530        assert_eq!(
531            map.get(ACCEPT_ENCODING),
532            Some(&HeaderValue::from_static("gzip"))
533        );
534        assert_eq!(
535            map.get_mut(ACCEPT_ENCODING),
536            Some(&mut HeaderValue::from_static("gzip"))
537        );
538
539        map.remove(ACCEPT_ENCODING);
540        assert_eq!(map.get(ACCEPT_ENCODING), None);
541    }
542
543    #[test]
544    fn test_from_http() {
545        let mut map = http::HeaderMap::new();
546        map.append(ACCEPT_ENCODING, http::HeaderValue::from_static("gzip"));
547
548        let map2 = HeaderMap::from(map);
549        assert_eq!(
550            map2.get(ACCEPT_ENCODING),
551            Some(&HeaderValue::from_static("gzip"))
552        );
553    }
554
555    #[test]
556    fn value_into_iter() {
557        let mut it = Value::One(HeaderValue::from_static("a")).into_iter();
558        assert_eq!(it.size_hint(), (1, Some(1)));
559        assert_eq!(it.next(), Some(HeaderValue::from_static("a")));
560        assert_eq!(it.size_hint(), (0, Some(0)));
561        assert_eq!(it.next(), None);
562
563        let mut val = Value::One(HeaderValue::from_static("a"));
564        val.append(HeaderValue::from_static("b"));
565        val.append(HeaderValue::from_static("c"));
566        let mut it = val.into_iter();
567        assert_eq!(it.size_hint(), (3, Some(3)));
568        assert_eq!(it.next(), Some(HeaderValue::from_static("a")));
569        assert_eq!(it.next(), Some(HeaderValue::from_static("b")));
570        assert_eq!(it.size_hint(), (1, Some(1)));
571        assert_eq!(it.next(), Some(HeaderValue::from_static("c")));
572        assert_eq!(it.next(), None);
573        assert_eq!(it.next(), None);
574    }
575}