static_web_server/headers_ext/
content_coding.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2// Original code by Parker Timmerman
3// Original code sourced from https://github.com/hyperium/headers/pull/70
4
5// Derives an enum to represent content codings and some helpful impls
6macro_rules! define_content_coding {
7    ($($coding:ident; $str:expr,)+) => {
8        use hyper::header::HeaderValue;
9        use std::str::FromStr;
10
11        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
12        /// Values that are used with headers like [`Content-Encoding`](headers::ContentEncoding) or
13        /// [`Accept-Encoding`](super::AcceptEncoding)
14        ///
15        /// [RFC7231](https://www.iana.org/assignments/http-parameters/http-parameters.xhtml)
16        pub enum ContentCoding {
17            $(
18                #[allow(clippy::upper_case_acronyms)]
19                #[doc = $str]
20                $coding,
21            )+
22        }
23
24        impl ContentCoding {
25            /// Returns a `&'static str` for a `ContentCoding`
26            #[inline]
27            pub(crate) fn as_str(&self) -> &'static str {
28                match *self {
29                    $(ContentCoding::$coding => $str,)+
30                }
31            }
32        }
33
34        impl From<&str> for ContentCoding {
35            /// Given a `&str` returns a `ContentCoding`
36            ///
37            /// Note this will never fail, in the case of `&str` being an invalid content coding,
38            /// will return `ContentCoding::IDENTITY` because `'identity'` is generally always an
39            /// accepted coding.
40            #[inline]
41            fn from(s: &str) -> Self {
42                ContentCoding::from_str(s).unwrap_or_else(|_| ContentCoding::IDENTITY)
43            }
44        }
45
46        impl FromStr for ContentCoding {
47            type Err = ();
48
49            /// Given a `&str` will try to return a `ContentCoding`
50            ///
51            /// Different from `ContentCoding::from(&str)`, if `&str` is an invalid content
52            /// coding, it will return `Err(())`
53            #[inline]
54            fn from_str(s: &str) -> Result<Self, Self::Err> {
55                match s {
56                    $(
57                        stringify!($coding)
58                        | $str => Ok(Self::$coding),
59                    )+
60                    _ => Err(())
61                }
62            }
63        }
64
65        impl std::fmt::Display for ContentCoding {
66            #[inline]
67            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
68                write!(f, "{}", match *self {
69                    $(ContentCoding::$coding => $str.to_string(),)+
70                })
71            }
72        }
73
74        impl From<ContentCoding> for HeaderValue {
75            fn from(coding: ContentCoding) -> HeaderValue {
76                match coding {
77                    $(ContentCoding::$coding => HeaderValue::from_static($str),)+
78                }
79            }
80        }
81    }
82}
83
84define_content_coding! {
85    BROTLI; "br",
86    COMPRESS; "compress",
87    DEFLATE; "deflate",
88    GZIP; "gzip",
89    IDENTITY; "identity",
90    ZSTD; "zstd",
91}
92
93#[cfg(test)]
94mod tests {
95    use super::ContentCoding;
96    use std::str::FromStr;
97
98    #[test]
99    fn as_str() {
100        assert_eq!(ContentCoding::GZIP.as_str(), "gzip");
101    }
102
103    #[test]
104    fn to_string() {
105        assert_eq!(ContentCoding::DEFLATE.to_string(), "deflate".to_string());
106    }
107
108    #[test]
109    fn from() {
110        assert_eq!(ContentCoding::from("br"), ContentCoding::BROTLI);
111        assert_eq!(ContentCoding::from("GZIP"), ContentCoding::GZIP);
112        assert_eq!(ContentCoding::from("zstd"), ContentCoding::ZSTD);
113        assert_eq!(ContentCoding::from("blah blah"), ContentCoding::IDENTITY);
114    }
115
116    #[test]
117    fn from_str() {
118        assert_eq!(ContentCoding::from_str("br"), Ok(ContentCoding::BROTLI));
119        assert_eq!(ContentCoding::from_str("zstd"), Ok(ContentCoding::ZSTD));
120        assert_eq!(ContentCoding::from_str("blah blah"), Err(()));
121    }
122}