Skip to content

Commit fbaed33

Browse files
committed
Remove MatchDirective
1 parent 1c6889a commit fbaed33

File tree

5 files changed

+132
-126
lines changed

5 files changed

+132
-126
lines changed

src/conditional/etag.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,7 @@ impl ETag {
7979

8080
/// Get the `HeaderValue`.
8181
pub fn value(&self) -> HeaderValue {
82-
let s = match self {
83-
Self::Strong(s) => format!(r#""{}""#, s),
84-
Self::Weak(s) => format!(r#"W/"{}""#, s),
85-
};
82+
let s = self.to_string();
8683
// SAFETY: the internal string is validated to be ASCII.
8784
unsafe { HeaderValue::from_bytes_unchecked(s.into()) }
8885
}
@@ -97,6 +94,14 @@ impl ETag {
9794
matches!(self, Self::Weak(_))
9895
}
9996

97+
/// Convert an ETag to a String.
98+
pub fn to_string(&self) -> String {
99+
match self {
100+
Self::Strong(s) => format!(r#""{}""#, s),
101+
Self::Weak(s) => format!(r#"W/"{}""#, s),
102+
}
103+
}
104+
100105
/// Create an Etag from a string.
101106
pub(crate) fn from_str(s: &str) -> crate::Result<Self> {
102107
let mut weak = false;

src/conditional/if_match.rs

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Apply the HTTP method if the ETag matches.
22
3-
use crate::conditional::MatchDirective;
3+
use crate::conditional::ETag;
44
use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, IF_MATCH};
55

66
use std::fmt::{self, Debug, Write};
@@ -31,19 +31,20 @@ use std::slice;
3131
///
3232
/// let entries = IfMatch::from_headers(res)?.unwrap();
3333
/// let mut entries = entries.iter();
34-
/// assert_eq!(entries.next().unwrap(), ETag::new("0xcafebeef".to_string()));
35-
/// assert_eq!(entries.next().unwrap(), ETag::new("0xbeefcafe".to_string()));
34+
/// assert_eq!(entries.next().unwrap(), &ETag::new("0xcafebeef".to_string()));
35+
/// assert_eq!(entries.next().unwrap(), &ETag::new("0xbeefcafe".to_string()));
3636
/// #
3737
/// # Ok(()) }
3838
/// ```
3939
pub struct IfMatch {
40-
entries: Vec<MatchDirective>,
40+
entries: Vec<ETag>,
41+
wildcard: bool,
4142
}
4243

4344
impl IfMatch {
4445
/// Create a new instance of `IfMatch`.
4546
pub fn new() -> Self {
46-
Self { entries: vec![] }
47+
Self { entries: vec![], wildcard: false }
4748
}
4849

4950
/// Create a new instance from headers.
@@ -54,17 +55,20 @@ impl IfMatch {
5455
None => return Ok(None),
5556
};
5657

58+
let mut wildcard = false;
5759
for value in headers {
5860
for part in value.as_str().trim().split(',') {
59-
// Try and parse a directive from a str. If the directive is
60-
// unkown we skip it.
61-
if let Some(entry) = MatchDirective::from_str(part)? {
62-
entries.push(entry);
61+
let part = part.trim();
62+
if part == "*" {
63+
wildcard = true;
64+
continue;
6365
}
66+
entries.push(ETag::from_str(part)?);
6467
}
6568
}
6669

67-
Ok(Some(Self { entries }))
70+
Ok(Some(Self { entries, wildcard }))
71+
6872
}
6973

7074
/// Sets the `If-Match` header.
@@ -80,11 +84,17 @@ impl IfMatch {
8084
/// Get the `HeaderValue`.
8185
pub fn value(&self) -> HeaderValue {
8286
let mut output = String::new();
83-
for (n, directive) in self.entries.iter().enumerate() {
84-
let directive: HeaderValue = directive.clone().into();
87+
for (n, etag) in self.entries.iter().enumerate() {
8588
match n {
86-
0 => write!(output, "{}", directive).unwrap(),
87-
_ => write!(output, ", {}", directive).unwrap(),
89+
0 => write!(output, "{}", etag.to_string()).unwrap(),
90+
_ => write!(output, ", {}", etag.to_string()).unwrap(),
91+
};
92+
}
93+
94+
if self.wildcard {
95+
match output.len() {
96+
0 => write!(output, "*").unwrap(),
97+
_ => write!(output, ", *").unwrap(),
8898
};
8999
}
90100

@@ -93,10 +103,20 @@ impl IfMatch {
93103
}
94104

95105
/// Push a directive into the list of entries.
96-
pub fn push(&mut self, directive: impl Into<MatchDirective>) {
106+
pub fn push(&mut self, directive: impl Into<ETag>) {
97107
self.entries.push(directive.into());
98108
}
99109

110+
/// Returns `true` if a wildcard directive was set.
111+
pub fn wildcard(&self) -> bool {
112+
self.wildcard
113+
}
114+
115+
/// Set the wildcard directive.
116+
pub fn set_wildcard(&mut self, wildcard: bool) {
117+
self.wildcard = wildcard
118+
}
119+
100120
/// An iterator visiting all server entries.
101121
pub fn iter(&self) -> Iter<'_> {
102122
Iter {
@@ -113,7 +133,7 @@ impl IfMatch {
113133
}
114134

115135
impl IntoIterator for IfMatch {
116-
type Item = MatchDirective;
136+
type Item = ETag;
117137
type IntoIter = IntoIter;
118138

119139
#[inline]
@@ -125,7 +145,7 @@ impl IntoIterator for IfMatch {
125145
}
126146

127147
impl<'a> IntoIterator for &'a IfMatch {
128-
type Item = &'a MatchDirective;
148+
type Item = &'a ETag;
129149
type IntoIter = Iter<'a>;
130150

131151
#[inline]
@@ -135,7 +155,7 @@ impl<'a> IntoIterator for &'a IfMatch {
135155
}
136156

137157
impl<'a> IntoIterator for &'a mut IfMatch {
138-
type Item = &'a mut MatchDirective;
158+
type Item = &'a mut ETag;
139159
type IntoIter = IterMut<'a>;
140160

141161
#[inline]
@@ -147,11 +167,11 @@ impl<'a> IntoIterator for &'a mut IfMatch {
147167
/// A borrowing iterator over entries in `IfMatch`.
148168
#[derive(Debug)]
149169
pub struct IntoIter {
150-
inner: std::vec::IntoIter<MatchDirective>,
170+
inner: std::vec::IntoIter<ETag>,
151171
}
152172

153173
impl Iterator for IntoIter {
154-
type Item = MatchDirective;
174+
type Item = ETag;
155175

156176
fn next(&mut self) -> Option<Self::Item> {
157177
self.inner.next()
@@ -166,11 +186,11 @@ impl Iterator for IntoIter {
166186
/// A lending iterator over entries in `IfMatch`.
167187
#[derive(Debug)]
168188
pub struct Iter<'a> {
169-
inner: slice::Iter<'a, MatchDirective>,
189+
inner: slice::Iter<'a, ETag>,
170190
}
171191

172192
impl<'a> Iterator for Iter<'a> {
173-
type Item = &'a MatchDirective;
193+
type Item = &'a ETag;
174194

175195
fn next(&mut self) -> Option<Self::Item> {
176196
self.inner.next()
@@ -185,11 +205,11 @@ impl<'a> Iterator for Iter<'a> {
185205
/// A mutable iterator over entries in `IfMatch`.
186206
#[derive(Debug)]
187207
pub struct IterMut<'a> {
188-
inner: slice::IterMut<'a, MatchDirective>,
208+
inner: slice::IterMut<'a, ETag>,
189209
}
190210

191211
impl<'a> Iterator for IterMut<'a> {
192-
type Item = &'a mut MatchDirective;
212+
type Item = &'a mut ETag;
193213

194214
fn next(&mut self) -> Option<Self::Item> {
195215
self.inner.next()
@@ -235,8 +255,24 @@ mod test {
235255

236256
let entries = IfMatch::from_headers(res)?.unwrap();
237257
let mut entries = entries.iter();
238-
assert_eq!(entries.next().unwrap(), ETag::new("0xcafebeef".to_string()));
239-
assert_eq!(entries.next().unwrap(), ETag::new("0xbeefcafe".to_string()));
258+
assert_eq!(entries.next().unwrap(), &ETag::new("0xcafebeef".to_string()));
259+
assert_eq!(entries.next().unwrap(), &ETag::new("0xbeefcafe".to_string()));
260+
Ok(())
261+
}
262+
263+
#[test]
264+
fn wildcard() -> crate::Result<()> {
265+
let mut entries = IfMatch::new();
266+
entries.push(ETag::new("0xcafebeef".to_string()));
267+
entries.set_wildcard(true);
268+
269+
let mut res = Response::new(200);
270+
entries.apply(&mut res);
271+
272+
let entries = IfMatch::from_headers(res)?.unwrap();
273+
assert_eq!(entries.wildcard(), true);
274+
let mut entries = entries.iter();
275+
assert_eq!(entries.next().unwrap(), &ETag::new("0xcafebeef".to_string()));
240276
Ok(())
241277
}
242278
}

0 commit comments

Comments
 (0)