ntex_http/
map.rs

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