cogo_http/header/common/accept_ranges.rs
1use std::fmt::{self, Display};
2use std::str::FromStr;
3
4header! {
5 /// `Accept-Ranges` header, defined in
6 /// [RFC7233](http://tools.ietf.org/html/rfc7233#section-2.3)
7 ///
8 /// The `Accept-Ranges` header field allows a server to indicate that it
9 /// supports range requests for the target resource.
10 ///
11 /// # ABNF
12 /// ```plain
13 /// Accept-Ranges = acceptable-ranges
14 /// acceptable-ranges = 1#range-unit / \"none\"
15 ///
16 /// # Example values
17 /// * `bytes`
18 /// * `none`
19 /// * `unknown-unit`
20 /// ```
21 ///
22 /// # Examples
23 /// ```
24 /// use cogo_http::header::{Headers, AcceptRanges, RangeUnit};
25 ///
26 /// let mut headers = Headers::new();
27 /// headers.set(AcceptRanges(vec![RangeUnit::Bytes]));
28 /// ```
29 /// ```
30 /// use cogo_http::header::{Headers, AcceptRanges, RangeUnit};
31 ///
32 /// let mut headers = Headers::new();
33 /// headers.set(AcceptRanges(vec![RangeUnit::None]));
34 /// ```
35 /// ```
36 /// use cogo_http::header::{Headers, AcceptRanges, RangeUnit};
37 ///
38 /// let mut headers = Headers::new();
39 /// headers.set(
40 /// AcceptRanges(vec![
41 /// RangeUnit::Unregistered("nibbles".to_owned()),
42 /// RangeUnit::Bytes,
43 /// RangeUnit::Unregistered("doublets".to_owned()),
44 /// RangeUnit::Unregistered("quadlets".to_owned()),
45 /// ])
46 /// );
47 /// ```
48 (AcceptRanges, "Accept-Ranges") => (RangeUnit)+
49
50 test_acccept_ranges {
51 test_header!(test1, vec![b"bytes"]);
52 test_header!(test2, vec![b"none"]);
53 test_header!(test3, vec![b"unknown-unit"]);
54 test_header!(test4, vec![b"bytes, unknown-unit"]);
55 }
56}
57
58/// Range Units, described in [RFC7233](http://tools.ietf.org/html/rfc7233#section-2)
59///
60/// A representation can be partitioned into subranges according to
61/// various structural units, depending on the structure inherent in the
62/// representation's media type.
63///
64/// # ABNF
65/// ```plain
66/// range-unit = bytes-unit / other-range-unit
67/// bytes-unit = "bytes"
68/// other-range-unit = token
69/// ```
70#[derive(Clone, Debug, Eq, PartialEq)]
71pub enum RangeUnit {
72 /// Indicating byte-range requests are supported.
73 Bytes,
74 /// Reserved as keyword, indicating no ranges are supported.
75 None,
76 /// The given range unit is not registered at IANA.
77 Unregistered(String),
78}
79
80
81impl FromStr for RangeUnit {
82 type Err = crate::Error;
83 fn from_str(s: &str) -> crate::Result<Self> {
84 match s {
85 "bytes" => Ok(RangeUnit::Bytes),
86 "none" => Ok(RangeUnit::None),
87 // FIXME: Check if s is really a Token
88 _ => Ok(RangeUnit::Unregistered(s.to_owned())),
89 }
90 }
91}
92
93impl Display for RangeUnit {
94 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
95 match *self {
96 RangeUnit::Bytes => f.write_str("bytes"),
97 RangeUnit::None => f.write_str("none"),
98 RangeUnit::Unregistered(ref x) => f.write_str(&x),
99 }
100 }
101}