headers/common/
if_none_match.rs

1use super::ETag;
2use util::EntityTagRange;
3use HeaderValue;
4
5/// `If-None-Match` header, defined in
6/// [RFC7232](https://tools.ietf.org/html/rfc7232#section-3.2)
7///
8/// The `If-None-Match` header field makes the request method conditional
9/// on a recipient cache or origin server either not having any current
10/// representation of the target resource, when the field-value is "*",
11/// or having a selected representation with an entity-tag that does not
12/// match any of those listed in the field-value.
13///
14/// A recipient MUST use the weak comparison function when comparing
15/// entity-tags for If-None-Match (Section 2.3.2), since weak entity-tags
16/// can be used for cache validation even if there have been changes to
17/// the representation data.
18///
19/// # ABNF
20///
21/// ```text
22/// If-None-Match = "*" / 1#entity-tag
23/// ```
24///
25/// # Example values
26///
27/// * `"xyzzy"`
28/// * `W/"xyzzy"`
29/// * `"xyzzy", "r2d2xxxx", "c3piozzzz"`
30/// * `W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz"`
31/// * `*`
32///
33/// # Examples
34///
35/// ```
36/// # extern crate headers;
37/// use headers::IfNoneMatch;
38///
39/// let if_none_match = IfNoneMatch::any();
40/// ```
41#[derive(Clone, Debug, PartialEq)]
42pub struct IfNoneMatch(EntityTagRange);
43
44derive_header! {
45    IfNoneMatch(_),
46    name: IF_NONE_MATCH
47}
48
49impl IfNoneMatch {
50    /// Create a new `If-None-Match: *` header.
51    pub fn any() -> IfNoneMatch {
52        IfNoneMatch(EntityTagRange::Any)
53    }
54
55    /// Checks whether the ETag passes this precondition.
56    pub fn precondition_passes(&self, etag: &ETag) -> bool {
57        !self.0.matches_weak(&etag.0)
58    }
59}
60
61impl From<ETag> for IfNoneMatch {
62    fn from(etag: ETag) -> IfNoneMatch {
63        IfNoneMatch(EntityTagRange::Tags(HeaderValue::from(etag.0).into()))
64    }
65}
66
67/*
68test_if_none_match {
69    test_header!(test1, vec![b"\"xyzzy\""]);
70    test_header!(test2, vec![b"W/\"xyzzy\""]);
71    test_header!(test3, vec![b"\"xyzzy\", \"r2d2xxxx\", \"c3piozzzz\""]);
72    test_header!(test4, vec![b"W/\"xyzzy\", W/\"r2d2xxxx\", W/\"c3piozzzz\""]);
73    test_header!(test5, vec![b"*"]);
74}
75*/
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn precondition_fails() {
83        let foo = ETag::from_static("\"foo\"");
84        let weak_foo = ETag::from_static("W/\"foo\"");
85
86        let if_none = IfNoneMatch::from(foo.clone());
87
88        assert!(!if_none.precondition_passes(&foo));
89        assert!(!if_none.precondition_passes(&weak_foo));
90    }
91
92    #[test]
93    fn precondition_passes() {
94        let if_none = IfNoneMatch::from(ETag::from_static("\"foo\""));
95
96        let bar = ETag::from_static("\"bar\"");
97        let weak_bar = ETag::from_static("W/\"bar\"");
98
99        assert!(if_none.precondition_passes(&bar));
100        assert!(if_none.precondition_passes(&weak_bar));
101    }
102
103    #[test]
104    fn precondition_any() {
105        let foo = ETag::from_static("\"foo\"");
106
107        let if_none = IfNoneMatch::any();
108
109        assert!(!if_none.precondition_passes(&foo));
110    }
111}