rama_http_headers/common/
accept_ranges.rs

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