headers/common/
etag.rs

1use std::str::FromStr;
2use util::EntityTag;
3
4/// `ETag` header, defined in [RFC7232](http://tools.ietf.org/html/rfc7232#section-2.3)
5///
6/// The `ETag` header field in a response provides the current entity-tag
7/// for the selected representation, as determined at the conclusion of
8/// handling the request.  An entity-tag is an opaque validator for
9/// differentiating between multiple representations of the same
10/// resource, regardless of whether those multiple representations are
11/// due to resource state changes over time, content negotiation
12/// resulting in multiple representations being valid at the same time,
13/// or both.  An entity-tag consists of an opaque quoted string, possibly
14/// prefixed by a weakness indicator.
15///
16/// # ABNF
17///
18/// ```text
19/// ETag       = entity-tag
20/// ```
21///
22/// # Example values
23///
24/// * `"xyzzy"`
25/// * `W/"xyzzy"`
26/// * `""`
27///
28/// # Examples
29///
30/// ```
31/// let etag = "\"xyzzy\"".parse::<headers::ETag>().unwrap();
32/// ```
33#[derive(Clone, Debug, PartialEq, Eq)]
34pub struct ETag(pub(super) EntityTag);
35
36derive_header! {
37    ETag(_),
38    name: ETAG
39}
40
41impl ETag {
42    #[cfg(test)]
43    pub(crate) fn from_static(src: &'static str) -> ETag {
44        ETag(EntityTag::from_static(src))
45    }
46}
47
48error_type!(InvalidETag);
49
50impl FromStr for ETag {
51    type Err = InvalidETag;
52    fn from_str(src: &str) -> Result<Self, Self::Err> {
53        let val = src.parse().map_err(|_| InvalidETag { _inner: () })?;
54
55        EntityTag::from_owned(val)
56            .map(ETag)
57            .ok_or_else(|| InvalidETag { _inner: () })
58    }
59}
60
61/*
62test_etag {
63    // From the RFC
64    test_header!(test1,
65        vec![b"\"xyzzy\""],
66        Some(ETag(EntityTag::new(false, "xyzzy".to_owned()))));
67    test_header!(test2,
68        vec![b"W/\"xyzzy\""],
69        Some(ETag(EntityTag::new(true, "xyzzy".to_owned()))));
70    test_header!(test3,
71        vec![b"\"\""],
72        Some(ETag(EntityTag::new(false, "".to_owned()))));
73    // Own tests
74    test_header!(test4,
75        vec![b"\"foobar\""],
76        Some(ETag(EntityTag::new(false, "foobar".to_owned()))));
77    test_header!(test5,
78        vec![b"\"\""],
79        Some(ETag(EntityTag::new(false, "".to_owned()))));
80    test_header!(test6,
81        vec![b"W/\"weak-etag\""],
82        Some(ETag(EntityTag::new(true, "weak-etag".to_owned()))));
83    test_header!(test7,
84        vec![b"W/\"\x65\x62\""],
85        Some(ETag(EntityTag::new(true, "\u{0065}\u{0062}".to_owned()))));
86    test_header!(test8,
87        vec![b"W/\"\""],
88        Some(ETag(EntityTag::new(true, "".to_owned()))));
89    test_header!(test9,
90        vec![b"no-dquotes"],
91        None::<ETag>);
92    test_header!(test10,
93        vec![b"w/\"the-first-w-is-case-sensitive\""],
94        None::<ETag>);
95    test_header!(test11,
96        vec![b""],
97        None::<ETag>);
98    test_header!(test12,
99        vec![b"\"unmatched-dquotes1"],
100        None::<ETag>);
101    test_header!(test13,
102        vec![b"unmatched-dquotes2\""],
103        None::<ETag>);
104    test_header!(test14,
105        vec![b"matched-\"dquotes\""],
106        None::<ETag>);
107    test_header!(test15,
108        vec![b"\""],
109        None::<ETag>);
110}
111*/