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