actix_http/header/shared/
content_encoding.rs

1use std::str::FromStr;
2
3use derive_more::{Display, Error};
4use http::header::InvalidHeaderValue;
5
6use crate::{
7    error::ParseError,
8    header::{self, from_one_raw_str, Header, HeaderName, HeaderValue, TryIntoHeaderValue},
9    HttpMessage,
10};
11
12/// Error returned when a content encoding is unknown.
13#[derive(Debug, Display, Error)]
14#[display("unsupported content encoding")]
15pub struct ContentEncodingParseError;
16
17/// Represents a supported content encoding.
18///
19/// Includes a commonly-used subset of media types appropriate for use as HTTP content encodings.
20/// See [IANA HTTP Content Coding Registry].
21///
22/// [IANA HTTP Content Coding Registry]: https://www.iana.org/assignments/http-parameters/http-parameters.xhtml
23#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
24#[non_exhaustive]
25pub enum ContentEncoding {
26    /// Indicates the no-op identity encoding.
27    ///
28    /// I.e., no compression or modification.
29    Identity,
30
31    /// A format using the Brotli algorithm.
32    Brotli,
33
34    /// A format using the zlib structure with deflate algorithm.
35    Deflate,
36
37    /// Gzip algorithm.
38    Gzip,
39
40    /// Zstd algorithm.
41    Zstd,
42}
43
44impl ContentEncoding {
45    /// Convert content encoding to string.
46    #[inline]
47    pub const fn as_str(self) -> &'static str {
48        match self {
49            ContentEncoding::Brotli => "br",
50            ContentEncoding::Gzip => "gzip",
51            ContentEncoding::Deflate => "deflate",
52            ContentEncoding::Zstd => "zstd",
53            ContentEncoding::Identity => "identity",
54        }
55    }
56
57    /// Convert content encoding to header value.
58    #[inline]
59    pub const fn to_header_value(self) -> HeaderValue {
60        match self {
61            ContentEncoding::Brotli => HeaderValue::from_static("br"),
62            ContentEncoding::Gzip => HeaderValue::from_static("gzip"),
63            ContentEncoding::Deflate => HeaderValue::from_static("deflate"),
64            ContentEncoding::Zstd => HeaderValue::from_static("zstd"),
65            ContentEncoding::Identity => HeaderValue::from_static("identity"),
66        }
67    }
68}
69
70impl Default for ContentEncoding {
71    #[inline]
72    fn default() -> Self {
73        Self::Identity
74    }
75}
76
77impl FromStr for ContentEncoding {
78    type Err = ContentEncodingParseError;
79
80    fn from_str(enc: &str) -> Result<Self, Self::Err> {
81        let enc = enc.trim();
82
83        if enc.eq_ignore_ascii_case("br") {
84            Ok(ContentEncoding::Brotli)
85        } else if enc.eq_ignore_ascii_case("gzip") {
86            Ok(ContentEncoding::Gzip)
87        } else if enc.eq_ignore_ascii_case("deflate") {
88            Ok(ContentEncoding::Deflate)
89        } else if enc.eq_ignore_ascii_case("identity") {
90            Ok(ContentEncoding::Identity)
91        } else if enc.eq_ignore_ascii_case("zstd") {
92            Ok(ContentEncoding::Zstd)
93        } else {
94            Err(ContentEncodingParseError)
95        }
96    }
97}
98
99impl TryFrom<&str> for ContentEncoding {
100    type Error = ContentEncodingParseError;
101
102    fn try_from(val: &str) -> Result<Self, Self::Error> {
103        val.parse()
104    }
105}
106
107impl TryIntoHeaderValue for ContentEncoding {
108    type Error = InvalidHeaderValue;
109
110    fn try_into_value(self) -> Result<http::HeaderValue, Self::Error> {
111        Ok(HeaderValue::from_static(self.as_str()))
112    }
113}
114
115impl Header for ContentEncoding {
116    fn name() -> HeaderName {
117        header::CONTENT_ENCODING
118    }
119
120    fn parse<T: HttpMessage>(msg: &T) -> Result<Self, ParseError> {
121        from_one_raw_str(msg.headers().get(Self::name()))
122    }
123}