headers/
map_ext.rs
1use super::{Error, Header, HeaderValue};
2use http;
3
4pub trait HeaderMapExt: self::sealed::Sealed {
6 fn typed_insert<H>(&mut self, header: H)
8 where
9 H: Header;
10
11 fn typed_get<H>(&self) -> Option<H>
13 where
14 H: Header;
15
16 fn typed_try_get<H>(&self) -> Result<Option<H>, Error>
18 where
19 H: Header;
20}
21
22impl HeaderMapExt for http::HeaderMap {
23 fn typed_insert<H>(&mut self, header: H)
24 where
25 H: Header,
26 {
27 let entry = self.entry(H::name());
28 let mut values = ToValues {
29 state: State::First(entry),
30 };
31 header.encode(&mut values);
32 }
33
34 fn typed_get<H>(&self) -> Option<H>
35 where
36 H: Header,
37 {
38 HeaderMapExt::typed_try_get(self).unwrap_or(None)
39 }
40
41 fn typed_try_get<H>(&self) -> Result<Option<H>, Error>
42 where
43 H: Header,
44 {
45 let mut values = self.get_all(H::name()).iter();
46 if values.size_hint() == (0, Some(0)) {
47 Ok(None)
48 } else {
49 H::decode(&mut values).map(Some)
50 }
51 }
52}
53
54struct ToValues<'a> {
55 state: State<'a>,
56}
57
58#[derive(Debug)]
59enum State<'a> {
60 First(http::header::Entry<'a, HeaderValue>),
61 Latter(http::header::OccupiedEntry<'a, HeaderValue>),
62 Tmp,
63}
64
65impl<'a> Extend<HeaderValue> for ToValues<'a> {
66 fn extend<T: IntoIterator<Item = HeaderValue>>(&mut self, iter: T) {
67 for value in iter {
68 let entry = match ::std::mem::replace(&mut self.state, State::Tmp) {
69 State::First(http::header::Entry::Occupied(mut e)) => {
70 e.insert(value);
71 e
72 }
73 State::First(http::header::Entry::Vacant(e)) => e.insert_entry(value),
74 State::Latter(mut e) => {
75 e.append(value);
76 e
77 }
78 State::Tmp => unreachable!("ToValues State::Tmp"),
79 };
80 self.state = State::Latter(entry);
81 }
82 }
83}
84
85mod sealed {
86 pub trait Sealed {}
87 impl Sealed for ::http::HeaderMap {}
88}