headers_accept_encoding/common/
content_coding.rs

1use HeaderValue;
2
3// Derives an enum to represent content codings and some helpful impls
4macro_rules! define_content_coding {
5    ($($coding:ident; $str:expr,)+) => {
6        #[derive(Copy, Clone, Debug, Eq, PartialEq)]
7        /// Values that are used with headers like [`Content-Encoding`](self::ContentEncoding) or
8        /// [`Accept-Encoding`](self::AcceptEncoding)
9        ///
10        /// [RFC7231](https://www.iana.org/assignments/http-parameters/http-parameters.xhtml)
11        pub enum ContentCoding {
12            $(
13                #[doc = $str]
14                $coding,
15            )+
16        }
17
18        impl ContentCoding {
19            /// Returns a `&'static str` for a `ContentCoding`
20            ///
21            /// # Example
22            ///
23            /// ```
24            /// use headers::ContentCoding;
25            ///
26            /// let coding = ContentCoding::BROTLI;
27            /// assert_eq!(coding.to_static(), "br");
28            /// ```
29            #[inline]
30            pub fn to_static(&self) -> &'static str {
31                match *self {
32                    $(ContentCoding::$coding => $str,)+
33                }
34            }
35
36            /// Given a `&str` returns a `ContentCoding`
37            ///
38            /// Note this will never fail, in the case of `&str` being an invalid content coding,
39            /// will return `ContentCoding::IDENTITY` because `'identity'` is generally always an
40            /// accepted coding.
41            ///
42            /// # Example
43            ///
44            /// ```
45            /// use headers::ContentCoding;
46            ///
47            /// let invalid = ContentCoding::from_str("not a valid coding");
48            /// assert_eq!(invalid, ContentCoding::IDENTITY);
49            ///
50            /// let valid = ContentCoding::from_str("gzip");
51            /// assert_eq!(valid, ContentCoding::GZIP);
52            /// ```
53            #[inline]
54            pub fn from_str(s: &str) -> Self {
55                ContentCoding::try_from_str(s).unwrap_or_else(|_| ContentCoding::IDENTITY)
56            }
57
58            /// Given a `&str` will try to return a `ContentCoding`
59            ///
60            /// Different from `ContentCoding::from_str(&str)`, if `&str` is an invalid content
61            /// coding, it will return `Err(())`
62            ///
63            /// # Example
64            ///
65            /// ```
66            /// use headers::ContentCoding;
67            ///
68            /// let invalid = ContentCoding::try_from_str("not a valid coding");
69            /// assert!(invalid.is_err());
70            ///
71            /// let valid = ContentCoding::try_from_str("gzip");
72            /// assert_eq!(valid.unwrap(), ContentCoding::GZIP);
73            /// ```
74            #[inline]
75            pub fn try_from_str(s: &str) -> Result<Self, ()> {
76                match s {
77                    $(
78                        stringify!($coding)
79                        | $str => Ok(ContentCoding::$coding),
80                    )+
81                    _ => Err(())
82                }
83            }
84        }
85
86        impl std::string::ToString for ContentCoding {
87            #[inline]
88            fn to_string(&self) -> String {
89                match *self {
90                    $(ContentCoding::$coding => $str.to_string(),)+
91                }
92            }
93        }
94
95        impl From<ContentCoding> for HeaderValue {
96            fn from(coding: ContentCoding) -> HeaderValue {
97                match coding {
98                    $(ContentCoding::$coding => HeaderValue::from_static($str),)+
99                }
100            }
101        }
102    }
103}
104
105define_content_coding! {
106    BROTLI; "br",
107    COMPRESS; "compress",
108    DEFLATE; "deflate",
109    GZIP; "gzip",
110    IDENTITY; "identity",
111    ZSTD; "zstd",
112}
113
114#[cfg(test)]
115mod tests {
116    use super::ContentCoding;
117
118    #[test]
119    fn to_static() {
120        assert_eq!(ContentCoding::GZIP.to_static(), "gzip");
121    }
122
123    #[test]
124    fn to_string() {
125        assert_eq!(ContentCoding::DEFLATE.to_string(), "deflate".to_string());
126    }
127
128    #[test]
129    fn from_str() {
130        assert_eq!(ContentCoding::from_str("br"), ContentCoding::BROTLI);
131        assert_eq!(ContentCoding::from_str("GZIP"), ContentCoding::GZIP);
132        assert_eq!(ContentCoding::from_str("zstd"), ContentCoding::ZSTD);
133        assert_eq!(
134            ContentCoding::from_str("blah blah"),
135            ContentCoding::IDENTITY
136        );
137    }
138
139    #[test]
140    fn try_from_str() {
141        assert_eq!(ContentCoding::try_from_str("br"), Ok(ContentCoding::BROTLI));
142        assert_eq!(ContentCoding::try_from_str("zstd"), Ok(ContentCoding::ZSTD));
143        assert_eq!(ContentCoding::try_from_str("blah blah"), Err(()));
144    }
145}