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