axol_http/header/
typed.rs

1use headers::HeaderValue;
2
3use crate::typed_headers::Header as HttpHeader;
4
5use super::HeaderMap;
6
7pub trait TypedHeader {
8    fn name() -> &'static str;
9
10    fn encode(&self, map: &mut HeaderMap);
11
12    fn encode_to_string(&self) -> Vec<String> {
13        let mut out = HeaderMap::default();
14        self.encode(&mut out);
15        out.into_iter()
16            .map(|(_, value)| value.into_owned())
17            .collect()
18    }
19
20    fn decode(from: &str) -> Result<Self, crate::typed_headers::Error>
21    where
22        Self: Sized;
23}
24
25struct HeaderValueProxy<'a> {
26    name: &'static str,
27    target: &'a mut HeaderMap,
28}
29
30impl<'a> Extend<http::HeaderValue> for HeaderValueProxy<'a> {
31    fn extend<T: IntoIterator<Item = http::HeaderValue>>(&mut self, iter: T) {
32        //TODO: unsafe transmute to get raw bytes out of HeaderValue?
33        self.target.extend(iter.into_iter().map(|x| {
34            (
35                self.name,
36                x.to_str()
37                    .expect("typed header had non-utf8 value")
38                    .to_string(),
39            )
40        }))
41    }
42}
43
44impl<H: HttpHeader> TypedHeader for H {
45    fn name() -> &'static str {
46        <Self as HttpHeader>::name().as_str()
47    }
48
49    fn encode(&self, map: &mut HeaderMap) {
50        <Self as HttpHeader>::encode(
51            self,
52            &mut HeaderValueProxy {
53                name: <Self as TypedHeader>::name(),
54                target: map,
55            },
56        );
57    }
58
59    fn decode(from: &str) -> Result<Self, crate::typed_headers::Error> {
60        let header = HeaderValue::from_bytes(from.as_bytes()).expect("invalid header value");
61        <Self as HttpHeader>::decode(&mut std::iter::once(&header))
62    }
63}