1use super::ETag;
2use util::EntityTagRange;
3use HeaderValue;
45/// `If-Match` header, defined in
6/// [RFC7232](https://tools.ietf.org/html/rfc7232#section-3.1)
7///
8/// The `If-Match` header field makes the request method conditional on
9/// the recipient origin server either having at least one current
10/// representation of the target resource, when the field-value is "*",
11/// or having a current representation of the target resource that has an
12/// entity-tag matching a member of the list of entity-tags provided in
13/// the field-value.
14///
15/// An origin server MUST use the strong comparison function when
16/// comparing entity-tags for `If-Match`, since the client
17/// intends this precondition to prevent the method from being applied if
18/// there have been any changes to the representation data.
19///
20/// # ABNF
21///
22/// ```text
23/// If-Match = "*" / 1#entity-tag
24/// ```
25///
26/// # Example values
27///
28/// * `"xyzzy"`
29/// * "xyzzy", "r2d2xxxx", "c3piozzzz"
30///
31/// # Examples
32///
33/// ```
34/// # extern crate headers;
35/// use headers::IfMatch;
36///
37/// let if_match = IfMatch::any();
38/// ```
39#[derive(Clone, Debug, PartialEq)]
40pub struct IfMatch(EntityTagRange);
4142derive_header! {
43 IfMatch(_),
44 name: IF_MATCH
45}
4647impl IfMatch {
48/// Create a new `If-Match: *` header.
49pub fn any() -> IfMatch {
50 IfMatch(EntityTagRange::Any)
51 }
5253/// Returns whether this is `If-Match: *`, matching any entity tag.
54pub fn is_any(&self) -> bool {
55match self.0 {
56 EntityTagRange::Any => true,
57 EntityTagRange::Tags(..) => false,
58 }
59 }
6061/// Checks whether the `ETag` strongly matches.
62pub fn precondition_passes(&self, etag: &ETag) -> bool {
63self.0.matches_strong(&etag.0)
64 }
65}
6667impl From<ETag> for IfMatch {
68fn from(etag: ETag) -> IfMatch {
69 IfMatch(EntityTagRange::Tags(HeaderValue::from(etag.0).into()))
70 }
71}
7273#[cfg(test)]
74mod tests {
75use super::*;
7677#[test]
78fn is_any() {
79assert!(IfMatch::any().is_any());
80assert!(!IfMatch::from(ETag::from_static("\"yolo\"")).is_any());
81 }
8283#[test]
84fn precondition_fails() {
85let if_match = IfMatch::from(ETag::from_static("\"foo\""));
8687let bar = ETag::from_static("\"bar\"");
88let weak_foo = ETag::from_static("W/\"foo\"");
8990assert!(!if_match.precondition_passes(&bar));
91assert!(!if_match.precondition_passes(&weak_foo));
92 }
9394#[test]
95fn precondition_passes() {
96let foo = ETag::from_static("\"foo\"");
9798let if_match = IfMatch::from(foo.clone());
99100assert!(if_match.precondition_passes(&foo));
101 }
102103#[test]
104fn precondition_any() {
105let foo = ETag::from_static("\"foo\"");
106107let if_match = IfMatch::any();
108109assert!(if_match.precondition_passes(&foo));
110 }
111}