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