Skip to content

Commit 56bed20

Browse files
committed
adapting accept encoding to use content coding
1 parent 2fe75b4 commit 56bed20

File tree

2 files changed

+95
-32
lines changed

2 files changed

+95
-32
lines changed

src/common/accept_encoding.rs

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::convert::TryFrom;
2+
3+
use {ContentCoding, HeaderValue};
24
use util::{QualityValue, TryFromValues};
3-
use HeaderValue;
45

56
/// `Accept-Encoding` header, defined in
67
/// [RFC7231](https://tools.ietf.org/html/rfc7231#section-5.3.4)
@@ -68,55 +69,75 @@ impl AcceptEncoding {
6869
/// # Example
6970
///
7071
/// ```
71-
/// use headers::AcceptEncoding;
72+
/// use headers::{AcceptEncoding, ContentCoding};
7273
///
7374
/// let pairs = vec![("gzip", 1.0), ("deflate", 0.8)];
7475
/// let accept_enc = AcceptEncoding::from_quality_pairs(&mut pairs.into_iter()).unwrap();
7576
/// let mut encodings = accept_enc.sorted_encodings();
7677
///
77-
/// assert_eq!(accept_enc.prefered_encoding(), Some("gzip"));
78+
/// assert_eq!(accept_enc.prefered_encoding(), Some(ContentCoding::GZIP));
7879
/// ```
79-
pub fn prefered_encoding(&self) -> Option<&str> {
80-
self.0.iter().peekable().peek().map(|s| *s)
80+
pub fn prefered_encoding(&self) -> Option<ContentCoding> {
81+
self.0.iter().peekable().peek().map(|s| ContentCoding::from_str(*s))
8182
}
8283

83-
/// Returns a quality sorted iterator of the accepted encodings
84+
/// Returns a quality sorted iterator of the `ContentCoding`
8485
///
8586
/// # Example
8687
///
8788
/// ```
88-
/// use headers::{AcceptEncoding, HeaderValue};
89+
/// use headers::{AcceptEncoding, ContentCoding, HeaderValue};
8990
///
9091
/// let val = HeaderValue::from_static("deflate, gzip;q=1.0, br;q=0.8");
9192
/// let accept_enc = AcceptEncoding(val.into());
9293
/// let mut encodings = accept_enc.sorted_encodings();
9394
///
95+
/// assert_eq!(encodings.next(), Some(ContentCoding::DEFLATE));
96+
/// assert_eq!(encodings.next(), Some(ContentCoding::GZIP));
97+
/// assert_eq!(encodings.next(), Some(ContentCoding::BROTLI));
98+
/// assert_eq!(encodings.next(), None);
99+
/// ```
100+
pub fn sorted_encodings<'a>(&'a self) -> impl Iterator<Item = ContentCoding> + 'a {
101+
self.0.iter().map(|s| ContentCoding::from_str(s))
102+
}
103+
104+
/// Returns a quality sorted iterator of values
105+
///
106+
/// # Example
107+
///
108+
/// ```
109+
/// use headers::{AcceptEncoding, ContentCoding, HeaderValue};
110+
///
111+
/// let val = HeaderValue::from_static("deflate, gzip;q=1.0, br;q=0.8");
112+
/// let accept_enc = AcceptEncoding(val.into());
113+
/// let mut encodings = accept_enc.sorted_values();
114+
///
94115
/// assert_eq!(encodings.next(), Some("deflate"));
95116
/// assert_eq!(encodings.next(), Some("gzip"));
96117
/// assert_eq!(encodings.next(), Some("br"));
97118
/// assert_eq!(encodings.next(), None);
98119
/// ```
99-
pub fn sorted_encodings(&self) -> impl Iterator<Item = &str> {
120+
pub fn sorted_values(&self) -> impl Iterator<Item = &str> {
100121
self.0.iter()
101122
}
102123
}
103124

104125
#[cfg(test)]
105126
mod tests {
106127
use super::*;
107-
use HeaderValue;
128+
use {ContentCoding, HeaderValue};
108129

109130
#[test]
110131
fn from_static() {
111132
let val = HeaderValue::from_static("deflate, gzip;q=1.0, br;q=0.9");
112133
let accept_enc = AcceptEncoding(val.into());
113134

114-
assert_eq!(accept_enc.prefered_encoding(), Some("deflate"));
135+
assert_eq!(accept_enc.prefered_encoding(), Some(ContentCoding::DEFLATE));
115136

116137
let mut encodings = accept_enc.sorted_encodings();
117-
assert_eq!(encodings.next(), Some("deflate"));
118-
assert_eq!(encodings.next(), Some("gzip"));
119-
assert_eq!(encodings.next(), Some("br"));
138+
assert_eq!(encodings.next(), Some(ContentCoding::DEFLATE));
139+
assert_eq!(encodings.next(), Some(ContentCoding::GZIP));
140+
assert_eq!(encodings.next(), Some(ContentCoding::BROTLI));
120141
assert_eq!(encodings.next(), None);
121142
}
122143

@@ -125,11 +146,11 @@ mod tests {
125146
let pairs = vec![("gzip", 1.0), ("br", 0.9)];
126147
let accept_enc = AcceptEncoding::from_quality_pairs(&mut pairs.into_iter()).unwrap();
127148

128-
assert_eq!(accept_enc.prefered_encoding(), Some("gzip"));
149+
assert_eq!(accept_enc.prefered_encoding(), Some(ContentCoding::GZIP));
129150

130151
let mut encodings = accept_enc.sorted_encodings();
131-
assert_eq!(encodings.next(), Some("gzip"));
132-
assert_eq!(encodings.next(), Some("br"));
152+
assert_eq!(encodings.next(), Some(ContentCoding::GZIP));
153+
assert_eq!(encodings.next(), Some(ContentCoding::BROTLI));
133154
assert_eq!(encodings.next(), None);
134155
}
135156
}

src/common/content_coding.rs

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,64 @@ macro_rules! define_content_coding {
1919
$(ContentCoding::$coding => $str,)+
2020
}
2121
}
22-
}
2322

24-
impl std::string::ToString for ContentCoding {
23+
/// Given a &str returns a ContentCoding.
24+
///
25+
/// Note this will never fail, in the case of `&str` being an invalid content coding,
26+
/// will return `ContentCoding::IDENTITY` because identity is generally always an
27+
/// accepted coding.
28+
///
29+
/// # Example
30+
///
31+
/// ```
32+
/// use headers::ContentCoding;
33+
///
34+
/// let invalid = ContentCoding::from_str("not a valid coding");
35+
/// assert_eq!(invalid, ContentCoding::IDENTITY);
36+
///
37+
/// let valid = ContentCoding::from_str("gzip");
38+
/// assert_eq!(valid, ContentCoding::GZIP);
39+
/// ```
40+
///
2541
#[inline]
26-
fn to_string(&self) -> String {
27-
match *self {
28-
$(ContentCoding::$coding => $str.to_string(),)+
29-
}
42+
pub fn from_str(s: &str) -> Self {
43+
ContentCoding::try_from_str(s).unwrap_or_else(|_| ContentCoding::IDENTITY)
3044
}
31-
}
32-
33-
impl std::str::FromStr for ContentCoding {
34-
type Err = &'static str;
3545

36-
fn from_str(s: &str) -> Result<Self, Self::Err> {
46+
#[inline]
47+
/// Given a &str will try to return a ContentCoding
48+
///
49+
/// Different from `ContentCoding::from_str(&str)`, if `&str` is an invalid content
50+
/// coding, it will return `Err(())`
51+
///
52+
/// # Example
53+
///
54+
/// ```
55+
/// use headers::ContentCoding;
56+
///
57+
/// let invalid = ContentCoding::try_from_str("not a valid coding");
58+
/// assert!(invalid.is_err());
59+
///
60+
/// let valid = ContentCoding::try_from_str("gzip");
61+
/// assert_eq!(valid.unwrap(), ContentCoding::GZIP);
62+
/// ```
63+
///
64+
pub fn try_from_str(s: &str) -> Result<Self, ()> {
3765
match s {
3866
$(
3967
stringify!($coding)
4068
| $str => Ok(ContentCoding::$coding),
4169
)+
42-
_ => Err("invalid content coding")
70+
_ => Err(())
71+
}
72+
}
73+
}
74+
75+
impl std::string::ToString for ContentCoding {
76+
#[inline]
77+
fn to_string(&self) -> String {
78+
match *self {
79+
$(ContentCoding::$coding => $str.to_string(),)+
4380
}
4481
}
4582
}
@@ -57,7 +94,6 @@ define_content_coding! {
5794
#[cfg(test)]
5895
mod tests {
5996
use super::ContentCoding;
60-
use std::str::FromStr;
6197

6298
#[test]
6399
fn to_static() {
@@ -71,8 +107,14 @@ mod tests {
71107

72108
#[test]
73109
fn from_str() {
74-
assert_eq!(ContentCoding::from_str("br"), Ok(ContentCoding::BROTLI));
75-
assert_eq!(ContentCoding::from_str("GZIP"), Ok(ContentCoding::GZIP));
76-
assert_eq!(ContentCoding::from_str("blah blah"), Err("invalid content coding"));
110+
assert_eq!(ContentCoding::from_str("br"), ContentCoding::BROTLI);
111+
assert_eq!(ContentCoding::from_str("GZIP"), ContentCoding::GZIP);
112+
assert_eq!(ContentCoding::from_str("blah blah"), ContentCoding::IDENTITY);
113+
}
114+
115+
#[test]
116+
fn try_from_str() {
117+
assert_eq!(ContentCoding::try_from_str("br"), Ok(ContentCoding::BROTLI));
118+
assert_eq!(ContentCoding::try_from_str("blah blah"), Err(()));
77119
}
78120
}

0 commit comments

Comments
 (0)