requiem_http/header/
map.rs

1use std::collections::hash_map::{self, Entry};
2use std::convert::TryFrom;
3
4use either::Either;
5use fxhash::FxHashMap;
6use http::header::{HeaderName, HeaderValue};
7
8/// A set of HTTP headers
9///
10/// `HeaderMap` is an multimap of [`HeaderName`] to values.
11///
12/// [`HeaderName`]: struct.HeaderName.html
13#[derive(Debug, Clone)]
14pub struct HeaderMap {
15    pub(crate) inner: FxHashMap<HeaderName, Value>,
16}
17
18#[derive(Debug, Clone)]
19pub(crate) enum Value {
20    One(HeaderValue),
21    Multi(Vec<HeaderValue>),
22}
23
24impl Value {
25    fn get(&self) -> &HeaderValue {
26        match self {
27            Value::One(ref val) => val,
28            Value::Multi(ref val) => &val[0],
29        }
30    }
31
32    fn get_mut(&mut self) -> &mut HeaderValue {
33        match self {
34            Value::One(ref mut val) => val,
35            Value::Multi(ref mut val) => &mut val[0],
36        }
37    }
38
39    fn append(&mut self, val: HeaderValue) {
40        match self {
41            Value::One(_) => {
42                let data = std::mem::replace(self, Value::Multi(vec![val]));
43                match data {
44                    Value::One(val) => self.append(val),
45                    Value::Multi(_) => unreachable!(),
46                }
47            }
48            Value::Multi(ref mut vec) => vec.push(val),
49        }
50    }
51}
52
53impl HeaderMap {
54    /// Create an empty `HeaderMap`.
55    ///
56    /// The map will be created without any capacity. This function will not
57    /// allocate.
58    pub fn new() -> Self {
59        HeaderMap {
60            inner: FxHashMap::default(),
61        }
62    }
63
64    /// Create an empty `HeaderMap` with the specified capacity.
65    ///
66    /// The returned map will allocate internal storage in order to hold about
67    /// `capacity` elements without reallocating. However, this is a "best
68    /// effort" as there are usage patterns that could cause additional
69    /// allocations before `capacity` headers are stored in the map.
70    ///
71    /// More capacity than requested may be allocated.
72    pub fn with_capacity(capacity: usize) -> HeaderMap {
73        HeaderMap {
74            inner: FxHashMap::with_capacity_and_hasher(capacity, Default::default()),
75        }
76    }
77
78    /// Returns the number of keys stored in the map.
79    ///
80    /// This number could be be less than or equal to actual headers stored in
81    /// the map.
82    pub fn len(&self) -> usize {
83        self.inner.len()
84    }
85
86    /// Returns true if the map contains no elements.
87    pub fn is_empty(&self) -> bool {
88        self.inner.len() == 0
89    }
90
91    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
92    /// for reuse.
93    pub fn clear(&mut self) {
94        self.inner.clear();
95    }
96
97    /// Returns the number of headers the map can hold without reallocating.
98    ///
99    /// This number is an approximation as certain usage patterns could cause
100    /// additional allocations before the returned capacity is filled.
101    pub fn capacity(&self) -> usize {
102        self.inner.capacity()
103    }
104
105    /// Reserves capacity for at least `additional` more headers to be inserted
106    /// into the `HeaderMap`.
107    ///
108    /// The header map may reserve more space to avoid frequent reallocations.
109    /// Like with `with_capacity`, this will be a "best effort" to avoid
110    /// allocations until `additional` more headers are inserted. Certain usage
111    /// patterns could cause additional allocations before the number is
112    /// reached.
113    pub fn reserve(&mut self, additional: usize) {
114        self.inner.reserve(additional)
115    }
116
117    /// Returns a reference to the value associated with the key.
118    ///
119    /// If there are multiple values associated with the key, then the first one
120    /// is returned. Use `get_all` to get all values associated with a given
121    /// key. Returns `None` if there are no values associated with the key.
122    pub fn get<N: AsName>(&self, name: N) -> Option<&HeaderValue> {
123        self.get2(name).map(|v| v.get())
124    }
125
126    fn get2<N: AsName>(&self, name: N) -> Option<&Value> {
127        match name.as_name() {
128            Either::Left(name) => self.inner.get(name),
129            Either::Right(s) => {
130                if let Ok(name) = HeaderName::try_from(s) {
131                    self.inner.get(&name)
132                } else {
133                    None
134                }
135            }
136        }
137    }
138
139    /// Returns a view of all values associated with a key.
140    ///
141    /// The returned view does not incur any allocations and allows iterating
142    /// the values associated with the key.  See [`GetAll`] for more details.
143    /// Returns `None` if there are no values associated with the key.
144    ///
145    /// [`GetAll`]: struct.GetAll.html
146    pub fn get_all<N: AsName>(&self, name: N) -> GetAll<'_> {
147        GetAll {
148            idx: 0,
149            item: self.get2(name),
150        }
151    }
152
153    /// Returns a mutable reference to the value associated with the key.
154    ///
155    /// If there are multiple values associated with the key, then the first one
156    /// is returned. Use `entry` to get all values associated with a given
157    /// key. Returns `None` if there are no values associated with the key.
158    pub fn get_mut<N: AsName>(&mut self, name: N) -> Option<&mut HeaderValue> {
159        match name.as_name() {
160            Either::Left(name) => self.inner.get_mut(name).map(|v| v.get_mut()),
161            Either::Right(s) => {
162                if let Ok(name) = HeaderName::try_from(s) {
163                    self.inner.get_mut(&name).map(|v| v.get_mut())
164                } else {
165                    None
166                }
167            }
168        }
169    }
170
171    /// Returns true if the map contains a value for the specified key.
172    pub fn contains_key<N: AsName>(&self, key: N) -> bool {
173        match key.as_name() {
174            Either::Left(name) => self.inner.contains_key(name),
175            Either::Right(s) => {
176                if let Ok(name) = HeaderName::try_from(s) {
177                    self.inner.contains_key(&name)
178                } else {
179                    false
180                }
181            }
182        }
183    }
184
185    /// An iterator visiting all key-value pairs.
186    ///
187    /// The iteration order is arbitrary, but consistent across platforms for
188    /// the same crate version. Each key will be yielded once per associated
189    /// value. So, if a key has 3 associated values, it will be yielded 3 times.
190    pub fn iter(&self) -> Iter<'_> {
191        Iter::new(self.inner.iter())
192    }
193
194    /// An iterator visiting all keys.
195    ///
196    /// The iteration order is arbitrary, but consistent across platforms for
197    /// the same crate version. Each key will be yielded only once even if it
198    /// has multiple associated values.
199    pub fn keys(&self) -> Keys<'_> {
200        Keys(self.inner.keys())
201    }
202
203    /// Inserts a key-value pair into the map.
204    ///
205    /// If the map did not previously have this key present, then `None` is
206    /// returned.
207    ///
208    /// If the map did have this key present, the new value is associated with
209    /// the key and all previous values are removed. **Note** that only a single
210    /// one of the previous values is returned. If there are multiple values
211    /// that have been previously associated with the key, then the first one is
212    /// returned. See `insert_mult` on `OccupiedEntry` for an API that returns
213    /// all values.
214    ///
215    /// The key is not updated, though; this matters for types that can be `==`
216    /// without being identical.
217    pub fn insert(&mut self, key: HeaderName, val: HeaderValue) {
218        let _ = self.inner.insert(key, Value::One(val));
219    }
220
221    /// Inserts a key-value pair into the map.
222    ///
223    /// If the map did not previously have this key present, then `false` is
224    /// returned.
225    ///
226    /// If the map did have this key present, the new value is pushed to the end
227    /// of the list of values currently associated with the key. The key is not
228    /// updated, though; this matters for types that can be `==` without being
229    /// identical.
230    pub fn append(&mut self, key: HeaderName, value: HeaderValue) {
231        match self.inner.entry(key) {
232            Entry::Occupied(mut entry) => entry.get_mut().append(value),
233            Entry::Vacant(entry) => {
234                entry.insert(Value::One(value));
235            }
236        }
237    }
238
239    /// Removes all headers for a particular header name from the map.
240    pub fn remove<N: AsName>(&mut self, key: N) {
241        match key.as_name() {
242            Either::Left(name) => {
243                let _ = self.inner.remove(name);
244            }
245            Either::Right(s) => {
246                if let Ok(name) = HeaderName::try_from(s) {
247                    let _ = self.inner.remove(&name);
248                }
249            }
250        }
251    }
252}
253
254#[doc(hidden)]
255pub trait AsName {
256    fn as_name(&self) -> Either<&HeaderName, &str>;
257}
258
259impl AsName for HeaderName {
260    fn as_name(&self) -> Either<&HeaderName, &str> {
261        Either::Left(self)
262    }
263}
264
265impl<'a> AsName for &'a HeaderName {
266    fn as_name(&self) -> Either<&HeaderName, &str> {
267        Either::Left(self)
268    }
269}
270
271impl<'a> AsName for &'a str {
272    fn as_name(&self) -> Either<&HeaderName, &str> {
273        Either::Right(self)
274    }
275}
276
277impl AsName for String {
278    fn as_name(&self) -> Either<&HeaderName, &str> {
279        Either::Right(self.as_str())
280    }
281}
282
283impl<'a> AsName for &'a String {
284    fn as_name(&self) -> Either<&HeaderName, &str> {
285        Either::Right(self.as_str())
286    }
287}
288
289pub struct GetAll<'a> {
290    idx: usize,
291    item: Option<&'a Value>,
292}
293
294impl<'a> Iterator for GetAll<'a> {
295    type Item = &'a HeaderValue;
296
297    #[inline]
298    fn next(&mut self) -> Option<&'a HeaderValue> {
299        if let Some(ref val) = self.item {
300            match val {
301                Value::One(ref val) => {
302                    self.item.take();
303                    Some(val)
304                }
305                Value::Multi(ref vec) => {
306                    if self.idx < vec.len() {
307                        let item = Some(&vec[self.idx]);
308                        self.idx += 1;
309                        item
310                    } else {
311                        self.item.take();
312                        None
313                    }
314                }
315            }
316        } else {
317            None
318        }
319    }
320}
321
322pub struct Keys<'a>(hash_map::Keys<'a, HeaderName, Value>);
323
324impl<'a> Iterator for Keys<'a> {
325    type Item = &'a HeaderName;
326
327    #[inline]
328    fn next(&mut self) -> Option<&'a HeaderName> {
329        self.0.next()
330    }
331}
332
333impl<'a> IntoIterator for &'a HeaderMap {
334    type Item = (&'a HeaderName, &'a HeaderValue);
335    type IntoIter = Iter<'a>;
336
337    fn into_iter(self) -> Self::IntoIter {
338        self.iter()
339    }
340}
341
342pub struct Iter<'a> {
343    idx: usize,
344    current: Option<(&'a HeaderName, &'a Vec<HeaderValue>)>,
345    iter: hash_map::Iter<'a, HeaderName, Value>,
346}
347
348impl<'a> Iter<'a> {
349    fn new(iter: hash_map::Iter<'a, HeaderName, Value>) -> Self {
350        Self {
351            iter,
352            idx: 0,
353            current: None,
354        }
355    }
356}
357
358impl<'a> Iterator for Iter<'a> {
359    type Item = (&'a HeaderName, &'a HeaderValue);
360
361    #[inline]
362    fn next(&mut self) -> Option<(&'a HeaderName, &'a HeaderValue)> {
363        if let Some(ref mut item) = self.current {
364            if self.idx < item.1.len() {
365                let item = (item.0, &item.1[self.idx]);
366                self.idx += 1;
367                return Some(item);
368            } else {
369                self.idx = 0;
370                self.current.take();
371            }
372        }
373        if let Some(item) = self.iter.next() {
374            match item.1 {
375                Value::One(ref value) => Some((item.0, value)),
376                Value::Multi(ref vec) => {
377                    self.current = Some((item.0, vec));
378                    self.next()
379                }
380            }
381        } else {
382            None
383        }
384    }
385}