Skip to content

Commit 54f898c

Browse files
committed
ContentEncoding should only contain a single encoding
1 parent a786fac commit 54f898c

File tree

1 file changed

+38
-141
lines changed

1 file changed

+38
-141
lines changed

src/content/content_encoding.rs

Lines changed: 38 additions & 141 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
use crate::content::{Encoding, EncodingProposal};
44
use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, CONTENT_ENCODING};
55

6-
use std::fmt::{self, Debug, Write};
7-
use std::iter::Iterator;
6+
use std::fmt::{self, Debug};
7+
use std::ops::{Deref, DerefMut};
88
use std::option;
9-
use std::slice;
109

1110
/// Specify the compression algorithm.
1211
///
@@ -21,49 +20,47 @@ use std::slice;
2120
/// #
2221
/// use http_types::Response;
2322
/// use http_types::content::{ContentEncoding, Encoding};
24-
/// let mut entries = ContentEncoding::new();
25-
/// entries.push(Encoding::Gzip);
26-
/// entries.push(Encoding::Identity);
23+
/// let mut encoding = ContentEncoding::new(Encoding::Gzip);
2724
///
2825
/// let mut res = Response::new(200);
29-
/// entries.apply(&mut res);
26+
/// encoding.apply(&mut res);
3027
///
31-
/// let entries = ContentEncoding::from_headers(res)?.unwrap();
32-
/// let mut entries = entries.iter();
33-
/// assert_eq!(entries.next().unwrap(), &Encoding::Gzip);
34-
/// assert_eq!(entries.next().unwrap(), &Encoding::Identity);
28+
/// let encoding = ContentEncoding::from_headers(res)?.unwrap();
29+
/// assert_eq!(encoding, &Encoding::Gzip);
3530
/// #
3631
/// # Ok(()) }
3732
/// ```
3833
pub struct ContentEncoding {
39-
entries: Vec<Encoding>,
34+
inner: Encoding,
4035
}
4136

4237
impl ContentEncoding {
4338
/// Create a new instance of `CacheControl`.
44-
pub fn new() -> Self {
45-
Self { entries: vec![] }
39+
pub fn new(encoding: Encoding) -> Self {
40+
Self { inner: encoding }
4641
}
4742

4843
/// Create a new instance from headers.
4944
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
50-
let mut entries = vec![];
5145
let headers = match headers.as_ref().get(CONTENT_ENCODING) {
5246
Some(headers) => headers,
5347
None => return Ok(None),
5448
};
5549

50+
let mut inner = None;
51+
5652
for value in headers {
5753
for part in value.as_str().trim().split(',') {
5854
// Try and parse a directive from a str. If the directive is
5955
// unkown we skip it.
6056
if let Some(entry) = Encoding::from_str(part) {
61-
entries.push(entry);
57+
inner = Some(entry);
6258
}
6359
}
6460
}
6561

66-
Ok(Some(Self { entries }))
62+
let inner = inner.expect("Headers instance with no entries found");
63+
Ok(Some(Self { inner }))
6764
}
6865

6966
/// Sets the `Server-Timing` header.
@@ -78,173 +75,73 @@ impl ContentEncoding {
7875

7976
/// Get the `HeaderValue`.
8077
pub fn value(&self) -> HeaderValue {
81-
let mut output = String::new();
82-
for (n, directive) in self.entries.iter().enumerate() {
83-
let directive: HeaderValue = directive.clone().into();
84-
match n {
85-
0 => write!(output, "{}", directive).unwrap(),
86-
_ => write!(output, ", {}", directive).unwrap(),
87-
};
88-
}
89-
90-
// SAFETY: the internal string is validated to be ASCII.
91-
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
92-
}
93-
/// Push a directive into the list of entries.
94-
pub fn push(&mut self, directive: Encoding) {
95-
self.entries.push(directive);
96-
}
97-
98-
/// An iterator visiting all server entries.
99-
pub fn iter(&self) -> Iter<'_> {
100-
Iter {
101-
inner: self.entries.iter(),
102-
}
103-
}
104-
105-
/// An iterator visiting all server entries.
106-
pub fn iter_mut(&mut self) -> IterMut<'_> {
107-
IterMut {
108-
inner: self.entries.iter_mut(),
109-
}
78+
self.inner.into()
11079
}
11180
}
11281

113-
impl IntoIterator for ContentEncoding {
114-
type Item = Encoding;
115-
type IntoIter = IntoIter;
116-
117-
#[inline]
118-
fn into_iter(self) -> Self::IntoIter {
119-
IntoIter {
120-
inner: self.entries.into_iter(),
121-
}
122-
}
123-
}
124-
125-
impl<'a> IntoIterator for &'a ContentEncoding {
126-
type Item = &'a Encoding;
127-
type IntoIter = Iter<'a>;
128-
129-
#[inline]
130-
fn into_iter(self) -> Self::IntoIter {
131-
self.iter()
132-
}
133-
}
134-
135-
impl<'a> IntoIterator for &'a mut ContentEncoding {
136-
type Item = &'a mut Encoding;
137-
type IntoIter = IterMut<'a>;
138-
139-
#[inline]
140-
fn into_iter(self) -> Self::IntoIter {
141-
self.iter_mut()
82+
impl ToHeaderValues for ContentEncoding {
83+
type Iter = option::IntoIter<HeaderValue>;
84+
fn to_header_values(&self) -> crate::Result<Self::Iter> {
85+
// A HeaderValue will always convert into itself.
86+
Ok(self.value().to_header_values().unwrap())
14287
}
14388
}
14489

145-
/// A borrowing iterator over entries in `CacheControl`.
146-
#[derive(Debug)]
147-
pub struct IntoIter {
148-
inner: std::vec::IntoIter<Encoding>,
149-
}
150-
151-
impl Iterator for IntoIter {
152-
type Item = Encoding;
153-
154-
fn next(&mut self) -> Option<Self::Item> {
155-
self.inner.next()
90+
impl Deref for ContentEncoding {
91+
type Target = Encoding;
92+
fn deref(&self) -> &Self::Target {
93+
&self.inner
15694
}
157-
158-
#[inline]
159-
fn size_hint(&self) -> (usize, Option<usize>) {
160-
self.inner.size_hint()
161-
}
162-
}
163-
164-
/// A lending iterator over entries in `CacheControl`.
165-
#[derive(Debug)]
166-
pub struct Iter<'a> {
167-
inner: slice::Iter<'a, Encoding>,
16895
}
16996

170-
impl<'a> Iterator for Iter<'a> {
171-
type Item = &'a Encoding;
172-
173-
fn next(&mut self) -> Option<Self::Item> {
174-
self.inner.next()
175-
}
176-
177-
#[inline]
178-
fn size_hint(&self) -> (usize, Option<usize>) {
179-
self.inner.size_hint()
97+
impl DerefMut for ContentEncoding {
98+
fn deref_mut(&mut self) -> &mut Self::Target {
99+
&mut self.inner
180100
}
181101
}
182102

183-
/// A mutable iterator over entries in `CacheControl`.
184-
#[derive(Debug)]
185-
pub struct IterMut<'a> {
186-
inner: slice::IterMut<'a, Encoding>,
187-
}
188-
189-
impl<'a> Iterator for IterMut<'a> {
190-
type Item = &'a mut Encoding;
191-
192-
fn next(&mut self) -> Option<Self::Item> {
193-
self.inner.next()
194-
}
195-
196-
#[inline]
197-
fn size_hint(&self) -> (usize, Option<usize>) {
198-
self.inner.size_hint()
103+
impl PartialEq<Encoding> for ContentEncoding {
104+
fn eq(&self, other: &Encoding) -> bool {
105+
&self.inner == other
199106
}
200107
}
201108

202-
impl ToHeaderValues for ContentEncoding {
203-
type Iter = option::IntoIter<HeaderValue>;
204-
fn to_header_values(&self) -> crate::Result<Self::Iter> {
205-
// A HeaderValue will always convert into itself.
206-
Ok(self.value().to_header_values().unwrap())
109+
impl PartialEq<&Encoding> for ContentEncoding {
110+
fn eq(&self, other: &&Encoding) -> bool {
111+
&&self.inner == other
207112
}
208113
}
209114

210115
impl From<Encoding> for ContentEncoding {
211116
fn from(encoding: Encoding) -> Self {
212-
Self {
213-
entries: vec![encoding],
214-
}
117+
Self { inner: encoding }
215118
}
216119
}
217120

218121
impl From<&Encoding> for ContentEncoding {
219122
fn from(encoding: &Encoding) -> Self {
220-
Self {
221-
entries: vec![*encoding],
222-
}
123+
Self { inner: *encoding }
223124
}
224125
}
225126

226127
impl From<EncodingProposal> for ContentEncoding {
227128
fn from(encoding: EncodingProposal) -> Self {
228129
Self {
229-
entries: vec![encoding.encoding],
130+
inner: encoding.encoding,
230131
}
231132
}
232133
}
233134

234135
impl From<&EncodingProposal> for ContentEncoding {
235136
fn from(encoding: &EncodingProposal) -> Self {
236137
Self {
237-
entries: vec![encoding.encoding],
138+
inner: encoding.encoding,
238139
}
239140
}
240141
}
241142

242143
impl Debug for ContentEncoding {
243144
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244-
let mut list = f.debug_list();
245-
for directive in &self.entries {
246-
list.entry(directive);
247-
}
248-
list.finish()
145+
self.inner.fmt(f)
249146
}
250147
}

0 commit comments

Comments
 (0)