headers/common/
accept_ranges.rs

1use http::HeaderValue;
2
3use crate::util::FlatCsv;
4
5/// `Accept-Ranges` header, defined in [RFC7233](https://datatracker.ietf.org/doc/html/rfc7233#section-2.3)
6///
7/// The `Accept-Ranges` header field allows a server to indicate that it
8/// supports range requests for the target resource.
9///
10/// # ABNF
11///
12/// ```text
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/// ```
25/// use headers::{AcceptRanges, HeaderMap, HeaderMapExt};
26///
27/// let mut headers = HeaderMap::new();
28///
29/// headers.typed_insert(AcceptRanges::bytes());
30/// ```
31#[derive(Clone, Debug, PartialEq)]
32pub struct AcceptRanges(FlatCsv);
33
34derive_header! {
35    AcceptRanges(_),
36    name: ACCEPT_RANGES
37}
38
39const ACCEPT_RANGES_BYTES: &str = "bytes";
40const ACCEPT_RANGES_NONE: &str = "none";
41
42impl AcceptRanges {
43    /// A constructor to easily create the common `Accept-Ranges: bytes` header.
44    pub fn bytes() -> Self {
45        AcceptRanges(HeaderValue::from_static(ACCEPT_RANGES_BYTES).into())
46    }
47
48    /// Check if the unit is `bytes`.
49    pub fn is_bytes(&self) -> bool {
50        self.0.value == ACCEPT_RANGES_BYTES
51    }
52
53    /// A constructor to easily create the common `Accept-Ranges: none` header.
54    pub fn none() -> Self {
55        AcceptRanges(HeaderValue::from_static(ACCEPT_RANGES_NONE).into())
56    }
57
58    /// Check if the unit is `none`.
59    pub fn is_none(&self) -> bool {
60        self.0.value == ACCEPT_RANGES_NONE
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::super::test_decode;
67    use super::*;
68
69    fn accept_ranges(s: &str) -> AcceptRanges {
70        test_decode(&[s]).unwrap()
71    }
72
73    // bytes
74    #[test]
75    fn bytes_constructor() {
76        assert_eq!(accept_ranges("bytes"), AcceptRanges::bytes());
77    }
78
79    #[test]
80    fn is_bytes_method_successful_with_bytes_ranges() {
81        assert!(accept_ranges("bytes").is_bytes());
82    }
83
84    #[test]
85    fn is_bytes_method_successful_with_bytes_ranges_by_constructor() {
86        assert!(AcceptRanges::bytes().is_bytes());
87    }
88
89    #[test]
90    fn is_bytes_method_failed_with_not_bytes_ranges() {
91        assert!(!accept_ranges("dummy").is_bytes());
92    }
93
94    // none
95    #[test]
96    fn none_constructor() {
97        assert_eq!(accept_ranges("none"), AcceptRanges::none());
98    }
99
100    #[test]
101    fn is_none_method_successful_with_none_ranges() {
102        assert!(accept_ranges("none").is_none());
103    }
104
105    #[test]
106    fn is_none_method_successful_with_none_ranges_by_constructor() {
107        assert!(AcceptRanges::none().is_none());
108    }
109
110    #[test]
111    fn is_none_method_failed_with_not_none_ranges() {
112        assert!(!accept_ranges("dummy").is_none());
113    }
114}