http_types/content/
content_encoding.rs

1//! Specify the compression algorithm.
2
3use crate::content::{Encoding, EncodingProposal};
4use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, CONTENT_ENCODING};
5
6use std::fmt::{self, Debug};
7use std::ops::{Deref, DerefMut};
8use std::option;
9
10/// Specify the compression algorithm.
11///
12/// # Specifications
13///
14/// - [RFC 7231, section 3.1.2.2: Content-Encoding](https://tools.ietf.org/html/rfc7231#section-3.1.2.2)
15///
16/// # Examples
17///
18/// ```
19/// # fn main() -> http_types::Result<()> {
20/// #
21/// use http_types::Response;
22/// use http_types::content::{ContentEncoding, Encoding};
23/// let mut encoding = ContentEncoding::new(Encoding::Gzip);
24///
25/// let mut res = Response::new(200);
26/// encoding.apply(&mut res);
27///
28/// let encoding = ContentEncoding::from_headers(res)?.unwrap();
29/// assert_eq!(encoding, &Encoding::Gzip);
30/// #
31/// # Ok(()) }
32/// ```
33pub struct ContentEncoding {
34    inner: Encoding,
35}
36
37impl ContentEncoding {
38    /// Create a new instance of `CacheControl`.
39    pub fn new(encoding: Encoding) -> Self {
40        Self { inner: encoding }
41    }
42
43    /// Create a new instance from headers.
44    pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
45        let headers = match headers.as_ref().get(CONTENT_ENCODING) {
46            Some(headers) => headers,
47            None => return Ok(None),
48        };
49
50        let mut inner = None;
51
52        for value in headers {
53            if let Some(entry) = Encoding::from_str(value.as_str()) {
54                inner = Some(entry);
55            }
56        }
57
58        let inner = inner.expect("Headers instance with no entries found");
59        Ok(Some(Self { inner }))
60    }
61
62    /// Sets the `Content-Encoding` header.
63    pub fn apply(&self, mut headers: impl AsMut<Headers>) {
64        headers.as_mut().insert(CONTENT_ENCODING, self.value());
65    }
66
67    /// Get the `HeaderName`.
68    pub fn name(&self) -> HeaderName {
69        CONTENT_ENCODING
70    }
71
72    /// Get the `HeaderValue`.
73    pub fn value(&self) -> HeaderValue {
74        self.inner.into()
75    }
76
77    /// Access the encoding kind.
78    pub fn encoding(&self) -> Encoding {
79        self.inner
80    }
81}
82
83impl ToHeaderValues for ContentEncoding {
84    type Iter = option::IntoIter<HeaderValue>;
85    fn to_header_values(&self) -> crate::Result<Self::Iter> {
86        // A HeaderValue will always convert into itself.
87        Ok(self.value().to_header_values().unwrap())
88    }
89}
90
91impl Deref for ContentEncoding {
92    type Target = Encoding;
93    fn deref(&self) -> &Self::Target {
94        &self.inner
95    }
96}
97
98impl DerefMut for ContentEncoding {
99    fn deref_mut(&mut self) -> &mut Self::Target {
100        &mut self.inner
101    }
102}
103
104impl PartialEq<Encoding> for ContentEncoding {
105    fn eq(&self, other: &Encoding) -> bool {
106        &self.inner == other
107    }
108}
109
110impl PartialEq<&Encoding> for ContentEncoding {
111    fn eq(&self, other: &&Encoding) -> bool {
112        &&self.inner == other
113    }
114}
115
116impl From<Encoding> for ContentEncoding {
117    fn from(encoding: Encoding) -> Self {
118        Self { inner: encoding }
119    }
120}
121
122impl From<&Encoding> for ContentEncoding {
123    fn from(encoding: &Encoding) -> Self {
124        Self { inner: *encoding }
125    }
126}
127
128impl From<EncodingProposal> for ContentEncoding {
129    fn from(encoding: EncodingProposal) -> Self {
130        Self {
131            inner: encoding.encoding,
132        }
133    }
134}
135
136impl From<&EncodingProposal> for ContentEncoding {
137    fn from(encoding: &EncodingProposal) -> Self {
138        Self {
139            inner: encoding.encoding,
140        }
141    }
142}
143
144impl Debug for ContentEncoding {
145    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
146        self.inner.fmt(f)
147    }
148}