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*/