darpi_headers/
lib.rs

1mod accept_encoding;
2
3pub use accept_encoding::AcceptEncoding;
4
5use darpi::header::{HeaderValue, ToStrError};
6use derive_more::Display;
7use std::convert::TryFrom;
8
9#[derive(Display, Debug, Copy, Clone, PartialEq)]
10pub enum EncodingType {
11    Gzip,
12    Deflate,
13    Identity,
14    Br,
15    Auto,
16}
17
18#[derive(Display, Debug)]
19pub enum Error {
20    UnknownStr(String),
21    ToStrError(ToStrError),
22}
23
24impl EncodingType {
25    #[inline]
26    pub fn quality(self) -> f64 {
27        match self {
28            Self::Br => 1.1,
29            Self::Gzip => 1.0,
30            Self::Deflate => 0.9,
31            Self::Identity | Self::Auto => 0.1,
32        }
33    }
34}
35
36impl<'a> From<&'a str> for EncodingType {
37    fn from(value: &'a str) -> Self {
38        match value {
39            "gzip" => Self::Gzip,
40            "deflate" => Self::Deflate,
41            "identity" => Self::Identity,
42            "br" => Self::Br,
43            _ => Self::Auto,
44        }
45    }
46}
47
48impl Into<&str> for EncodingType {
49    fn into(self) -> &'static str {
50        match self {
51            Self::Gzip => "gzip",
52            Self::Deflate => "deflate",
53            Self::Identity | Self::Auto => "identity",
54            Self::Br => "br",
55        }
56    }
57}
58
59pub struct ContentEncoding {
60    encoding_types: Vec<EncodingType>,
61}
62
63impl ContentEncoding {
64    pub fn append(&mut self, et: EncodingType) {
65        self.encoding_types.push(et)
66    }
67    pub fn merge(&mut self, other: ContentEncoding) {
68        for et in other.encoding_types {
69            self.append(et)
70        }
71    }
72}
73
74impl Into<HeaderValue> for ContentEncoding {
75    fn into(self) -> HeaderValue {
76        let types: Vec<&str> = self.encoding_types.into_iter().map(|t| t.into()).collect();
77        let types = types.join(", ");
78        HeaderValue::from_str(&types).expect("this cannot happen")
79    }
80}
81
82impl TryFrom<Option<&mut HeaderValue>> for ContentEncoding {
83    type Error = Error;
84
85    fn try_from(hv: Option<&mut HeaderValue>) -> Result<Self, Self::Error> {
86        let hv = match hv {
87            Some(s) => s,
88            None => {
89                return Ok(Self {
90                    encoding_types: vec![],
91                })
92            }
93        };
94
95        if hv.is_empty() {
96            return Ok(Self {
97                encoding_types: vec![],
98            });
99        }
100        let parts: Vec<&str> = hv
101            .to_str()
102            .map_err(|e| Error::ToStrError(e))?
103            .split(", ")
104            .collect();
105
106        let mut encoding_types = vec![];
107        for part in parts {
108            let et = EncodingType::from(part);
109            encoding_types.push(et);
110        }
111
112        Ok(Self { encoding_types })
113    }
114}
115
116impl TryFrom<&HeaderValue> for ContentEncoding {
117    type Error = Error;
118
119    fn try_from(hv: &HeaderValue) -> Result<Self, Self::Error> {
120        if hv.is_empty() {
121            return Ok(Self {
122                encoding_types: vec![],
123            });
124        }
125        let parts: Vec<&str> = hv
126            .to_str()
127            .map_err(|e| Error::ToStrError(e))?
128            .split(", ")
129            .collect();
130
131        let mut encoding_types = vec![];
132        for part in parts {
133            let et = EncodingType::from(part);
134            encoding_types.push(et);
135        }
136
137        Ok(Self { encoding_types })
138    }
139}
140
141impl IntoIterator for ContentEncoding {
142    type Item = EncodingType;
143    type IntoIter = std::vec::IntoIter<EncodingType>;
144
145    fn into_iter(self) -> Self::IntoIter {
146        self.encoding_types.into_iter()
147    }
148}