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}