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}