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