1 use std::{convert::Infallible, str::FromStr}; 2 3 use http::header::InvalidHeaderValue; 4 5 use crate::{ 6 error::ParseError, 7 header::{self, from_one_raw_str, Header, HeaderName, HeaderValue, IntoHeaderValue}, 8 HttpMessage, 9 }; 10 11 /// Represents a supported content encoding. 12 #[derive(Copy, Clone, PartialEq, Debug)] 13 pub enum ContentEncoding { 14 /// Automatically select encoding based on encoding negotiation. 15 Auto, 16 17 /// A format using the Brotli algorithm. 18 Br, 19 20 /// A format using the zlib structure with deflate algorithm. 21 Deflate, 22 23 /// Gzip algorithm. 24 Gzip, 25 26 // Zstd algorithm. 27 Zstd, 28 29 /// Indicates the identity function (i.e. no compression, nor modification). 30 Identity, 31 } 32 33 impl ContentEncoding { 34 /// Is the content compressed? 35 #[inline] is_compression(self) -> bool36 pub fn is_compression(self) -> bool { 37 matches!(self, ContentEncoding::Identity | ContentEncoding::Auto) 38 } 39 40 /// Convert content encoding to string 41 #[inline] as_str(self) -> &'static str42 pub fn as_str(self) -> &'static str { 43 match self { 44 ContentEncoding::Br => "br", 45 ContentEncoding::Gzip => "gzip", 46 ContentEncoding::Deflate => "deflate", 47 ContentEncoding::Zstd => "zstd", 48 ContentEncoding::Identity | ContentEncoding::Auto => "identity", 49 } 50 } 51 52 /// Default Q-factor (quality) value. 53 #[inline] quality(self) -> f6454 pub fn quality(self) -> f64 { 55 match self { 56 ContentEncoding::Br => 1.1, 57 ContentEncoding::Gzip => 1.0, 58 ContentEncoding::Deflate => 0.9, 59 ContentEncoding::Identity | ContentEncoding::Auto => 0.1, 60 ContentEncoding::Zstd => 0.0, 61 } 62 } 63 } 64 65 impl Default for ContentEncoding { default() -> Self66 fn default() -> Self { 67 Self::Identity 68 } 69 } 70 71 impl FromStr for ContentEncoding { 72 type Err = Infallible; 73 from_str(val: &str) -> Result<Self, Self::Err>74 fn from_str(val: &str) -> Result<Self, Self::Err> { 75 Ok(Self::from(val)) 76 } 77 } 78 79 impl From<&str> for ContentEncoding { from(val: &str) -> ContentEncoding80 fn from(val: &str) -> ContentEncoding { 81 let val = val.trim(); 82 83 if val.eq_ignore_ascii_case("br") { 84 ContentEncoding::Br 85 } else if val.eq_ignore_ascii_case("gzip") { 86 ContentEncoding::Gzip 87 } else if val.eq_ignore_ascii_case("deflate") { 88 ContentEncoding::Deflate 89 } else if val.eq_ignore_ascii_case("zstd") { 90 ContentEncoding::Zstd 91 } else { 92 ContentEncoding::default() 93 } 94 } 95 } 96 97 impl IntoHeaderValue for ContentEncoding { 98 type Error = InvalidHeaderValue; 99 try_into_value(self) -> Result<http::HeaderValue, Self::Error>100 fn try_into_value(self) -> Result<http::HeaderValue, Self::Error> { 101 Ok(HeaderValue::from_static(self.as_str())) 102 } 103 } 104 105 impl Header for ContentEncoding { name() -> HeaderName106 fn name() -> HeaderName { 107 header::CONTENT_ENCODING 108 } 109 parse<T: HttpMessage>(msg: &T) -> Result<Self, ParseError>110 fn parse<T: HttpMessage>(msg: &T) -> Result<Self, ParseError> { 111 from_one_raw_str(msg.headers().get(Self::name())) 112 } 113 } 114