axol_http/header/
map.rs

1use std::{borrow::Cow, ops::Index};
2
3use http::{header::ToStrError, HeaderName, HeaderValue};
4use smallvec::SmallVec;
5use thiserror::Error;
6
7use super::{header_name, TypedHeader};
8
9/// This is a multimap representing HTTP headers.
10/// Not that this is not a true hashmap, as the count of headers is generally too small to be worth representing as a map.
11#[derive(Default, Clone, Debug, PartialEq, Eq)]
12pub struct HeaderMap {
13    items: Vec<(Cow<'static, str>, Cow<'static, str>)>,
14}
15
16#[cfg(feature = "otel")]
17impl opentelemetry_api::propagation::Extractor for &HeaderMap {
18    /// Get a value for a key from the HeaderMap.  If the value is not valid ASCII, returns None.
19    fn get(&self, key: &str) -> Option<&str> {
20        (&**self).get(key)
21    }
22
23    /// Collect all the keys from the HeaderMap.
24    fn keys(&self) -> Vec<&str> {
25        self.iter().map(|x| x.0).collect()
26    }
27}
28
29#[cfg(feature = "otel")]
30impl opentelemetry_api::propagation::Injector for &mut HeaderMap {
31    fn set(&mut self, key: &str, value: String) {
32        self.append(key, value);
33    }
34}
35
36impl HeaderMap {
37    /// Create an empty `HeaderMap`.
38    ///
39    /// The map will be created without any capacity. This function will not
40    /// allocate.
41    ///
42    /// # Examples
43    ///
44    /// ```
45    /// # use axol_http::HeaderMap;
46    /// let map = HeaderMap::new();
47    ///
48    /// assert!(map.is_empty());
49    /// assert_eq!(0, map.capacity());
50    /// ```
51    pub fn new() -> Self {
52        Default::default()
53    }
54
55    /// Create an empty `HeaderMap` with the specified capacity.
56    ///
57    /// The returned map will allocate internal storage in order to hold about
58    /// `capacity` elements without reallocating. However, this is a "best
59    /// effort" as there are usage patterns that could cause additional
60    /// allocations before `capacity` headers are stored in the map.
61    ///
62    /// More capacity than requested may be allocated.
63    ///
64    /// # Examples
65    ///
66    /// ```
67    /// # use axol_http::HeaderMap;
68    /// let map: HeaderMap<u32> = HeaderMap::with_capacity(10);
69    ///
70    /// assert!(map.is_empty());
71    /// assert_eq!(12, map.capacity());
72    /// ```
73    pub fn with_capacity(capacity: usize) -> Self {
74        Self {
75            items: Vec::with_capacity(capacity),
76        }
77    }
78
79    /// Returns the number of headers the map can hold without reallocating.
80    ///
81    /// This number is an approximation as certain usage patterns could cause
82    /// additional allocations before the returned capacity is filled.
83    ///
84    /// # Examples
85    ///
86    /// ```
87    /// # use axol_http::HeaderMap;
88    /// # use axol_http::header::HOST;
89    /// let mut map = HeaderMap::new();
90    ///
91    /// assert_eq!(0, map.capacity());
92    ///
93    /// map.insert(HOST, "hello.world".parse().unwrap());
94    /// assert_eq!(6, map.capacity());
95    /// ```
96    pub fn capacity(&self) -> usize {
97        self.items.capacity()
98    }
99
100    /// Reserves capacity for at least `additional` more headers to be inserted
101    /// into the `HeaderMap`.
102    ///
103    /// The header map may reserve more space to avoid frequent reallocations.
104    /// Like with `with_capacity`, this will be a "best effort" to avoid
105    /// allocations until `additional` more headers are inserted. Certain usage
106    /// patterns could cause additional allocations before the number is
107    /// reached.
108    ///
109    /// # Panics
110    ///
111    /// Panics if the new allocation size overflows `usize`.
112    ///
113    /// # Examples
114    ///
115    /// ```
116    /// # use axol_http::HeaderMap;
117    /// # use axol_http::header::HOST;
118    /// let mut map = HeaderMap::new();
119    /// map.reserve(10);
120    /// # map.insert(HOST, "bar".parse().unwrap());
121    /// ```
122    pub fn reserve(&mut self, additional: usize) {
123        self.items.reserve(additional);
124    }
125
126    /// Clears the map, removing all key-value pairs. Keeps the allocated memory
127    /// for reuse.
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// # use axol_http::HeaderMap;
133    /// # use axol_http::header::HOST;
134    /// let mut map = HeaderMap::new();
135    /// map.insert(HOST, "hello.world".parse().unwrap());
136    ///
137    /// map.clear();
138    /// assert!(map.is_empty());
139    /// assert!(map.capacity() > 0);
140    /// ```
141    pub fn clear(&mut self) {
142        self.items.clear();
143    }
144
145    /// Returns true if the map contains no elements.
146    ///
147    /// # Examples
148    ///
149    /// ```
150    /// # use axol_http::HeaderMap;
151    /// # use axol_http::header::HOST;
152    /// let mut map = HeaderMap::new();
153    ///
154    /// assert!(map.is_empty());
155    ///
156    /// map.insert(HOST, "hello.world".parse().unwrap());
157    ///
158    /// assert!(!map.is_empty());
159    /// ```
160    pub fn is_empty(&self) -> bool {
161        self.items.len() == 0
162    }
163
164    /// Returns the number of headers stored in the map.
165    ///
166    /// This number represents the total number of **values** stored in the map.
167    /// This number can be greater than or equal to the number of **keys**
168    /// stored given that a single key may have more than one associated value.
169    ///
170    /// # Examples
171    ///
172    /// ```
173    /// # use axol_http::HeaderMap;
174    /// # use axol_http::header::{ACCEPT, HOST};
175    /// let mut map = HeaderMap::new();
176    ///
177    /// assert_eq!(0, map.len());
178    ///
179    /// map.insert(ACCEPT, "text/plain".parse().unwrap());
180    /// map.insert(HOST, "localhost".parse().unwrap());
181    ///
182    /// assert_eq!(2, map.len());
183    ///
184    /// map.append(ACCEPT, "text/html".parse().unwrap());
185    ///
186    /// assert_eq!(3, map.len());
187    /// ```
188    pub fn len(&self) -> usize {
189        self.items.len()
190    }
191
192    /// Appends a key-value pair into the map.
193    ///
194    /// If the map did have this key present, the new value is pushed to the end
195    /// of the list of values currently associated with the key. The key is not
196    /// updated, though; this matters for types that can be `==` without being
197    /// identical.
198    ///
199    /// # Examples
200    ///
201    /// ```
202    /// # use axol_http::HeaderMap;
203    /// # use axol_http::header::HOST;
204    /// let mut map = HeaderMap::new();
205    /// assert!(map.insert(HOST, "world".parse().unwrap()).is_none());
206    /// assert!(!map.is_empty());
207    ///
208    /// map.append(HOST, "earth".parse().unwrap());
209    ///
210    /// let values = map.get_all("host");
211    /// let mut i = values.iter();
212    /// assert_eq!("world", *i.next().unwrap());
213    /// assert_eq!("earth", *i.next().unwrap());
214    /// ```
215    pub fn append(&mut self, name: impl AsRef<str>, value: impl Into<String>) {
216        let name = header_name(name.as_ref());
217        self.items.push((name, Cow::Owned(value.into())));
218    }
219
220    /// Appends a key-value pair into the map with a static value.
221    ///
222    /// If the map did have this key present, the new value is pushed to the end
223    /// of the list of values currently associated with the key. The key is not
224    /// updated, though; this matters for types that can be `==` without being
225    /// identical.
226    ///
227    /// # Examples
228    ///
229    /// ```
230    /// # use axol_http::HeaderMap;
231    /// # use axol_http::header::HOST;
232    /// let mut map = HeaderMap::new();
233    /// assert!(map.insert(HOST, "world".parse().unwrap()).is_none());
234    /// assert!(!map.is_empty());
235    ///
236    /// map.append(HOST, "earth".parse().unwrap());
237    ///
238    /// let values = map.get_all("host");
239    /// let mut i = values.iter();
240    /// assert_eq!("world", *i.next().unwrap());
241    /// assert_eq!("earth", *i.next().unwrap());
242    /// ```
243    pub fn append_static(&mut self, name: impl AsRef<str>, value: impl Into<&'static str>) {
244        let name = header_name(name.as_ref());
245        self.items.push((name, Cow::Borrowed(value.into())));
246    }
247
248    /// Appends a typed key-value pair into the map.
249    ///
250    /// If the map did have this key present, the new value is pushed to the end
251    /// of the list of values currently associated with the key. The key is not
252    /// updated, though; this matters for types that can be `==` without being
253    /// identical.
254    ///
255    /// # Examples
256    ///
257    /// ```
258    /// # use axol_http::HeaderMap;
259    /// # use axol_http::header::HOST;
260    /// let mut map = HeaderMap::new();
261    /// assert!(map.insert(HOST, "world".parse().unwrap()).is_none());
262    /// assert!(!map.is_empty());
263    ///
264    /// map.append(HOST, "earth".parse().unwrap());
265    ///
266    /// let values = map.get_all("host");
267    /// let mut i = values.iter();
268    /// assert_eq!("world", *i.next().unwrap());
269    /// assert_eq!("earth", *i.next().unwrap());
270    /// ```
271    pub fn append_typed<H: TypedHeader>(&mut self, header: &H) {
272        header.encode(self);
273    }
274
275    /// Inserts a key-value pair into the map.
276    ///
277    /// If the map did have this key present, the new value is associated with
278    /// the key and all previous values are removed. **Note** that only a single
279    /// one of the previous values is returned. If there are multiple values
280    /// that have been previously associated with the key, then the first one is
281    /// returned. See `insert_mult` on `OccupiedEntry` for an API that returns
282    /// all values.
283    ///
284    /// The key is not updated, though; this matters for types that can be `==`
285    /// without being identical.
286    ///
287    /// # Examples
288    ///
289    /// ```
290    /// # use axol_http::HeaderMap;
291    /// # use axol_http::header::HOST;
292    /// let mut map = HeaderMap::new();
293    /// assert!(map.insert(HOST, "world".parse().unwrap()).is_none());
294    /// assert!(!map.is_empty());
295    ///
296    /// let mut prev = map.insert(HOST, "earth".parse().unwrap()).unwrap();
297    /// assert_eq!("world", prev);
298    /// ```
299    pub fn insert(
300        &mut self,
301        name: impl AsRef<str>,
302        value: impl Into<String>,
303    ) -> Option<Cow<'static, str>> {
304        let name = header_name(name.as_ref());
305        match self.get_mut(&name) {
306            Some(old) => Some(std::mem::replace(old, Cow::Owned(value.into()))),
307            None => {
308                self.items.push((name, Cow::Owned(value.into())));
309                None
310            }
311        }
312    }
313
314    /// Inserts a key-value pair into the map with a static value.
315    ///
316    /// If the map did have this key present, the new value is associated with
317    /// the key and all previous values are removed. **Note** that only a single
318    /// one of the previous values is returned. If there are multiple values
319    /// that have been previously associated with the key, then the first one is
320    /// returned. See `insert_mult` on `OccupiedEntry` for an API that returns
321    /// all values.
322    ///
323    /// The key is not updated, though; this matters for types that can be `==`
324    /// without being identical.
325    ///
326    /// # Examples
327    ///
328    /// ```
329    /// # use axol_http::HeaderMap;
330    /// # use axol_http::header::HOST;
331    /// let mut map = HeaderMap::new();
332    /// assert!(map.insert(HOST, "world".parse().unwrap()).is_none());
333    /// assert!(!map.is_empty());
334    ///
335    /// let mut prev = map.insert(HOST, "earth".parse().unwrap()).unwrap();
336    /// assert_eq!("world", prev);
337    /// ```
338    pub fn insert_static(
339        &mut self,
340        name: impl AsRef<str>,
341        value: impl Into<&'static str>,
342    ) -> Option<Cow<'static, str>> {
343        let name = header_name(name.as_ref());
344        match self.get_mut(&name) {
345            Some(old) => Some(std::mem::replace(old, Cow::Borrowed(value.into()))),
346            None => {
347                self.items.push((name, Cow::Borrowed(value.into())));
348                None
349            }
350        }
351    }
352
353    /// Inserts a typed key-value pair into the map.
354    ///
355    /// Note that if the header is a TypedHeader with multiple values returned, only the last value is used.
356    ///
357    /// If the map did have this key present, the new value is associated with
358    /// the key and all previous values are removed. **Note** that only a single
359    /// one of the previous values is returned. If there are multiple values
360    /// that have been previously associated with the key, then the first one is
361    /// returned. See `insert_mult` on `OccupiedEntry` for an API that returns
362    /// all values.
363    ///
364    /// The key is not updated, though; this matters for types that can be `==`
365    /// without being identical.
366    ///
367    /// # Examples
368    ///
369    /// ```
370    /// # use axol_http::HeaderMap;
371    /// # use axol_http::header::HOST;
372    /// let mut map = HeaderMap::new();
373    /// assert!(map.insert(HOST, "world".parse().unwrap()).is_none());
374    /// assert!(!map.is_empty());
375    ///
376    /// let mut prev = map.insert(HOST, "earth".parse().unwrap()).unwrap();
377    /// assert_eq!("world", prev);
378    /// ```
379    pub fn insert_typed<H: TypedHeader>(&mut self, header: &H) -> Option<Cow<'static, str>> {
380        let name = H::name();
381        let value = header
382            .encode_to_string()
383            .into_iter()
384            .rev()
385            .next()
386            .expect("header encoded to empty value");
387        match self.get_mut(name) {
388            Some(old) => Some(std::mem::replace(old, Cow::Owned(value))),
389            None => {
390                self.items.push((Cow::Borrowed(name), Cow::Owned(value)));
391                None
392            }
393        }
394    }
395
396    /// Returns true if the map contains a value for the specified key.
397    ///
398    /// # Examples
399    ///
400    /// ```
401    /// # use axol_http::HeaderMap;
402    /// # use axol_http::header::HOST;
403    /// let mut map = HeaderMap::new();
404    /// assert!(!map.contains_key(HOST));
405    ///
406    /// map.insert(HOST, "world".parse().unwrap());
407    /// assert!(map.contains_key("host"));
408    /// ```
409    pub fn contains_key(&self, name: &str) -> bool {
410        self.get_all(name).next().is_some()
411    }
412
413    /// Returns a reference to the value associated with the key.
414    ///
415    /// If there are multiple values associated with the key, then the first one
416    /// is returned. Use `get_all` to get all values associated with a given
417    /// key. Returns `None` if there are no values associated with the key.
418    ///
419    /// # Examples
420    ///
421    /// ```
422    /// # use axol_http::HeaderMap;
423    /// # use axol_http::header::HOST;
424    /// let mut map = HeaderMap::new();
425    /// assert!(map.get("host").is_none());
426    ///
427    /// map.insert(HOST, "hello".parse().unwrap());
428    /// assert_eq!(map.get(HOST).unwrap(), &"hello");
429    /// assert_eq!(map.get("host").unwrap(), &"hello");
430    ///
431    /// map.append(HOST, "world".parse().unwrap());
432    /// assert_eq!(map.get("host").unwrap(), &"hello");
433    /// ```
434    pub fn get(&self, name: &str) -> Option<&str> {
435        self.items
436            .iter()
437            .find(|(entry_name, _)| entry_name.eq_ignore_ascii_case(name))
438            .map(|x| &*x.1)
439    }
440
441    /// Returns a reference to the value associated with the key.
442    ///
443    /// The key is defined with an associated type referenced a TypedHeader.
444    /// If the header is malformed, None is transparently returned
445    ///
446    /// Note that this causes an allocation depending on the implementation of the TypedHeader.
447    ///
448    /// If there are multiple values associated with the key, then the first one
449    /// is returned. Use `get_all` to get all values associated with a given
450    /// key. Returns `None` if there are no values associated with the key.
451    ///
452    /// # Examples
453    ///
454    /// ```
455    /// # use axol_http::HeaderMap;
456    /// # use axol_http::header::HOST;
457    /// let mut map = HeaderMap::new();
458    /// assert!(map.get::<Host>().is_none());
459    ///
460    /// map.insert(HOST, "hello".parse().unwrap());
461    /// assert_eq!(map.get::<Host>().unwrap(), &"hello");
462    ///
463    /// map.append(HOST, "world".parse().unwrap());
464    /// assert_eq!(map.get::<Host>().unwrap(), &"hello");
465    /// ```
466    pub fn get_typed<H: TypedHeader>(&self) -> Option<H> {
467        let raw = self.get(H::name())?;
468        H::decode(raw).ok()
469    }
470
471    /// Returns a view of all values associated with a key.
472    ///
473    /// The returned view does not incur any allocations and allows iterating
474    /// the values associated with the key.  See [`GetAll`] for more details.
475    /// Returns `None` if there are no values associated with the key.
476    ///
477    /// # Examples
478    ///
479    /// ```
480    /// # use axol_http::HeaderMap;
481    /// # use axol_http::header::HOST;
482    /// let mut map = HeaderMap::new();
483    ///
484    /// map.insert(HOST, "hello".parse().unwrap());
485    /// map.append(HOST, "goodbye".parse().unwrap());
486    ///
487    /// let view = map.get_all("host");
488    ///
489    /// let mut iter = view.iter();
490    /// assert_eq!(&"hello", iter.next().unwrap());
491    /// assert_eq!(&"goodbye", iter.next().unwrap());
492    /// assert!(iter.next().is_none());
493    /// ```
494    pub fn get_all<'a>(&'a self, name: &'a str) -> impl Iterator<Item = &'a str> {
495        self.items
496            .iter()
497            .filter(|(entry_name, _)| entry_name.eq_ignore_ascii_case(name))
498            .map(|x| &*x.1)
499    }
500
501    /// Returns a view of all values associated with a key.
502    ///
503    /// The key is defined with an associated type referenced a TypedHeader.
504    /// If the header is malformed, it is skipped.
505    ///
506    /// Note that this causes an allocation for each header value returned depending on the implementation of the TypedHeader.
507    ///
508    /// The returned view does not incur any allocations and allows iterating
509    /// the values associated with the key.  See [`GetAll`] for more details.
510    /// Returns `None` if there are no values associated with the key.
511    ///
512    /// # Examples
513    ///
514    /// ```
515    /// # use axol_http::HeaderMap;
516    /// # use axol_http::header::HOST;
517    /// let mut map = HeaderMap::new();
518    ///
519    /// map.insert(HOST, "hello".parse().unwrap());
520    /// map.append(HOST, "goodbye".parse().unwrap());
521    ///
522    /// let view = map.get_all("host");
523    ///
524    /// let mut iter = view.iter();
525    /// assert_eq!(&"hello", iter.next().unwrap());
526    /// assert_eq!(&"goodbye", iter.next().unwrap());
527    /// assert!(iter.next().is_none());
528    /// ```
529    pub fn get_all_typed<'a, H: TypedHeader>(&'a self) -> impl Iterator<Item = H> + 'a {
530        let name = H::name();
531        self.items
532            .iter()
533            .filter(|(entry_name, _)| entry_name.eq_ignore_ascii_case(name))
534            .filter_map(|x| H::decode(&*x.1).ok())
535    }
536
537    /// Returns a mutable reference to the value associated with the key.
538    ///
539    /// If there are multiple values associated with the key, then the first one
540    /// is returned. Use `entry` to get all values associated with a given
541    /// key. Returns `None` if there are no values associated with the key.
542    ///
543    /// # Examples
544    ///
545    /// ```
546    /// # use axol_http::HeaderMap;
547    /// # use axol_http::header::HOST;
548    /// let mut map = HeaderMap::default();
549    /// map.insert(HOST, "hello".to_string());
550    /// map.get_mut("host").unwrap().push_str("-world");
551    ///
552    /// assert_eq!(map.get(HOST).unwrap(), &"hello-world");
553    /// ```
554    pub fn get_mut(&mut self, name: &str) -> Option<&mut Cow<'static, str>> {
555        self.items
556            .iter_mut()
557            .find(|(entry_name, _)| entry_name.eq_ignore_ascii_case(name))
558            .map(|x| &mut x.1)
559    }
560
561    /// Removes a key from the map, returning the value associated with the key.
562    ///
563    /// Returns an empty vec if the map does not contain the key. If there are
564    /// multiple values associated with the key, then all are returned.
565    ///
566    /// # Examples
567    ///
568    /// ```
569    /// # use axol_http::HeaderMap;
570    /// # use axol_http::header::HOST;
571    /// let mut map = HeaderMap::new();
572    /// map.insert(HOST, "hello.world".parse().unwrap());
573    ///
574    /// let prev = map.remove(HOST);
575    /// assert_eq!("hello.world", &prev[0]);
576    ///
577    /// assert!(map.remove(HOST).is_empty());
578    /// ```
579    pub fn remove(&mut self, name: impl AsRef<str>) -> Vec<Cow<'static, str>> {
580        let name = name.as_ref();
581        let mut out = vec![];
582        self.items.retain_mut(|(entry_name, value)| {
583            if entry_name.eq_ignore_ascii_case(name) {
584                out.push(std::mem::take(value));
585                false
586            } else {
587                true
588            }
589        });
590        out
591    }
592
593    /// An iterator visiting all key-value pairs.
594    ///
595    /// The iteration order is in insertion order.
596    ///
597    /// # Examples
598    ///
599    /// ```
600    /// # use axol_http::HeaderMap;
601    /// # use axol_http::header::{CONTENT_LENGTH, HOST};
602    /// let mut map = HeaderMap::new();
603    ///
604    /// map.insert(HOST, "hello".parse().unwrap());
605    /// map.append(HOST, "goodbye".parse().unwrap());
606    /// map.insert(CONTENT_LENGTH, "123".parse().unwrap());
607    ///
608    /// for (key, value) in map.iter() {
609    ///     println!("{:?}: {:?}", key, value);
610    /// }
611    /// ```
612    pub fn iter(&self) -> impl Iterator<Item = (&str, &str)> {
613        self.items.iter().map(|(name, value)| (&**name, &**value))
614    }
615
616    pub fn grouped(&self) -> Vec<(&str, SmallVec<[&str; 2]>)> {
617        let mut names = self.iter().collect::<Vec<_>>();
618        names.sort_by_key(|x| x.0);
619        let mut out: Vec<(&str, SmallVec<[&str; 2]>)> = vec![];
620        for (name, value) in names {
621            if out.last().map(|x| x.0) == Some(name) {
622                out.last_mut().unwrap().1.push(value);
623            } else {
624                out.push((name, smallvec::smallvec![value]))
625            }
626        }
627
628        out
629    }
630}
631
632impl<K: Into<Cow<'static, str>>, V: Into<String>> Extend<(K, V)> for HeaderMap {
633    fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
634        let iter = iter.into_iter();
635        self.reserve(iter.size_hint().0);
636        for (name, value) in iter {
637            let name = name.into();
638            self.append(name, value);
639        }
640    }
641}
642
643impl<K: Into<Cow<'static, str>>, V: Into<String>> FromIterator<(K, V)> for HeaderMap {
644    fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
645        let mut out = Self::default();
646        out.extend(iter);
647        out
648    }
649}
650
651impl<K: Into<Cow<'static, str>>> Index<K> for HeaderMap {
652    type Output = str;
653
654    fn index(&self, index: K) -> &Self::Output {
655        self.get(index.into().as_ref()).expect("header missing")
656    }
657}
658
659impl IntoIterator for HeaderMap {
660    type Item = (Cow<'static, str>, Cow<'static, str>);
661
662    type IntoIter = std::vec::IntoIter<Self::Item>;
663
664    fn into_iter(self) -> Self::IntoIter {
665        self.items.into_iter()
666    }
667}
668
669impl<'a> IntoIterator for &'a HeaderMap {
670    type Item = &'a (Cow<'static, str>, Cow<'static, str>);
671
672    type IntoIter = std::slice::Iter<'a, (Cow<'static, str>, Cow<'static, str>)>;
673
674    fn into_iter(self) -> Self::IntoIter {
675        self.items.iter()
676    }
677}
678
679impl<'a> IntoIterator for &'a mut HeaderMap {
680    type Item = &'a mut (Cow<'static, str>, Cow<'static, str>);
681
682    type IntoIter = std::slice::IterMut<'a, (Cow<'static, str>, Cow<'static, str>)>;
683
684    fn into_iter(self) -> Self::IntoIter {
685        self.items.iter_mut()
686    }
687}
688
689#[derive(Error, Debug)]
690pub enum HeaderMapConvertError {
691    #[error("header value not utf8: '{0}'")]
692    Utf8(#[from] ToStrError),
693}
694
695impl TryFrom<http::HeaderMap> for HeaderMap {
696    type Error = HeaderMapConvertError;
697
698    fn try_from(value: http::HeaderMap) -> Result<Self, Self::Error> {
699        let mut out = Self::with_capacity(value.len());
700        let mut last_header_name = None::<http::HeaderName>;
701        for (name, value) in value.into_iter() {
702            let name_ref = match &name {
703                Some(x) => x,
704                None => last_header_name.as_ref().unwrap(),
705            };
706
707            out.append(name_ref.as_str(), value.to_str()?);
708
709            if let Some(name) = name {
710                last_header_name = Some(name);
711            }
712        }
713        Ok(out)
714    }
715}
716
717impl Into<http::HeaderMap> for HeaderMap {
718    fn into(self) -> http::HeaderMap {
719        self.into_iter()
720            .map(|(name, value)| {
721                (
722                    match name {
723                        Cow::Borrowed(x) => HeaderName::from_static(x),
724                        Cow::Owned(x) => {
725                            HeaderName::from_bytes(x.as_bytes()).expect("invalid header name")
726                        }
727                    },
728                    match value {
729                        Cow::Borrowed(x) => HeaderValue::from_static(x),
730                        Cow::Owned(x) => {
731                            HeaderValue::from_bytes(x.as_bytes()).expect("invalid header value")
732                        }
733                    },
734                )
735            })
736            .collect()
737    }
738}