11//! Apply the HTTP method if the ETag matches.
22
3- use crate :: conditional:: MatchDirective ;
3+ use crate :: conditional:: ETag ;
44use crate :: headers:: { HeaderName , HeaderValue , Headers , ToHeaderValues , IF_MATCH } ;
55
66use 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/// ```
3939pub struct IfMatch {
40- entries : Vec < MatchDirective > ,
40+ entries : Vec < ETag > ,
41+ wildcard : bool ,
4142}
4243
4344impl 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
115135impl 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
127147impl < ' 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
137157impl < ' 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 ) ]
149169pub struct IntoIter {
150- inner : std:: vec:: IntoIter < MatchDirective > ,
170+ inner : std:: vec:: IntoIter < ETag > ,
151171}
152172
153173impl 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 ) ]
168188pub struct Iter < ' a > {
169- inner : slice:: Iter < ' a , MatchDirective > ,
189+ inner : slice:: Iter < ' a , ETag > ,
170190}
171191
172192impl < ' 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 ) ]
187207pub struct IterMut < ' a > {
188- inner : slice:: IterMut < ' a , MatchDirective > ,
208+ inner : slice:: IterMut < ' a , ETag > ,
189209}
190210
191211impl < ' 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