http_status_codes2/
lib.rs

1//! Provides a representation of
2//! [IANA's](https://www.iana.org/)
3//! [HTTP Status Code Registry](https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml)
4//! and search functions to query it.
5//!
6//! A CLI is provided by the [heman](https://docs.rs/heman) crate.
7#![deny(missing_docs)]
8pub mod status_code_registry;
9
10use convert_case::{Case, Casing};
11
12/// Search for a HTTP status by its code in a given registry.
13///
14/// Exaple:
15/// ```rust
16/// use http_status_codes2::{find_by_code, status_code_registry::CODE_REGISTRY};
17///
18/// assert_eq!(
19///     find_by_code(100, &CODE_REGISTRY),
20///     Some((
21///         100,
22///         "Continue",
23///         "[RFC9110, Section 15.2.1]",
24///         "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.2.1"
25///     ))
26/// );
27/// assert_eq!(find_by_code(600, &CODE_REGISTRY), None);
28/// ```
29pub fn find_by_code(
30    code: usize,
31    registry: &[(usize, &'static str, &'static str, &'static str)],
32) -> Option<(usize, &'static str, &'static str, &'static str)> {
33    Some(*registry.iter().find(|&&it| it.0 == code)?)
34}
35
36/// Search a given registry for a HTTP statuses containing a substring (needle) in their description. Returns an iterator over the results.
37///
38/// Example:
39///
40/// ```rust
41/// use http_status_codes2::{find_by_substring, status_code_registry::UNOFFICIAL_CODE_REGISTRY};
42///
43/// let mut it = find_by_substring("teapot", &UNOFFICIAL_CODE_REGISTRY);
44/// assert_eq!(
45///     it.next(),
46///     Some((
47///         418,
48///         "I'm a teapot",
49///         "[RFC2324, Section 2.3.2]",
50///         "https://www.rfc-editor.org/rfc/rfc2324.html#section-2.3.2"
51///     ))
52///     .as_ref()
53/// );
54/// assert_eq!(it.next(), None);
55/// ```
56pub fn find_by_substring<'a>(
57    needle: &'a str,
58    registry: &'static [(usize, &'static str, &'static str, &'static str)],
59) -> impl Iterator<Item = &'static (usize, &'static str, &'static str, &'static str)> + 'a {
60    registry.iter().filter(move |&&it| {
61        it.1.to_case(Case::Lower)
62            .contains(&needle.to_case(Case::Lower))
63    })
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use status_code_registry::{CODE_REGISTRY, UNOFFICIAL_CODE_REGISTRY};
70
71    #[test]
72    fn test_find_by_code_ok() {
73        assert_eq!(
74            find_by_code(100, &CODE_REGISTRY),
75            Some((
76                100,
77                "Continue",
78                "[RFC9110, Section 15.2.1]",
79                "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.2.1"
80            ))
81        );
82    }
83    #[test]
84    fn test_find_by_code_nok() {
85        assert_eq!(find_by_code(600, &CODE_REGISTRY), None);
86    }
87
88    #[test]
89    fn test_find_by_code_unofficial_ok() {
90        assert_eq!(
91            find_by_code(418, &UNOFFICIAL_CODE_REGISTRY),
92            Some((
93                418,
94                "I'm a teapot",
95                "[RFC2324, Section 2.3.2]",
96                "https://www.rfc-editor.org/rfc/rfc2324.html#section-2.3.2"
97            ))
98        );
99    }
100
101    #[test]
102    fn test_find_by_code_unofficial_nok() {
103        assert_eq!(find_by_code(600, &UNOFFICIAL_CODE_REGISTRY), None);
104    }
105
106    #[test]
107    fn test_find_by_substring_ok() {
108        let mut it = find_by_substring("failed", &CODE_REGISTRY);
109        assert_eq!(
110            it.next(),
111            Some((
112                412,
113                "Precondition Failed",
114                "[RFC9110, Section 15.5.13]",
115                "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.13"
116            ))
117            .as_ref()
118        );
119        assert_eq!(
120            it.next(),
121            Some((
122                417,
123                "Expectation Failed",
124                "[RFC9110, Section 15.5.18]",
125                "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.18"
126            ))
127            .as_ref()
128        );
129        assert_eq!(
130            it.next(),
131            Some((
132                424,
133                "Failed Dependency",
134                "[RFC4918]",
135                "https://www.rfc-editor.org/rfc/rfc4918.html"
136            ))
137            .as_ref()
138        );
139        assert_eq!(it.next(), None);
140    }
141
142    #[test]
143    fn test_find_by_substring_nok() {
144        let mut it = find_by_substring("teapot", &CODE_REGISTRY);
145        assert_eq!(it.next(), None);
146    }
147
148    #[test]
149    fn test_find_by_substring_unofficial_ok() {
150        let mut it = find_by_substring("teapot", &UNOFFICIAL_CODE_REGISTRY);
151        assert_eq!(
152            it.next(),
153            Some((
154                418,
155                "I'm a teapot",
156                "[RFC2324, Section 2.3.2]",
157                "https://www.rfc-editor.org/rfc/rfc2324.html#section-2.3.2"
158            ))
159            .as_ref()
160        );
161    }
162
163    #[test]
164    fn test_find_by_substring_unofficial_nok() {
165        let mut it = find_by_substring("Prince Adam", &UNOFFICIAL_CODE_REGISTRY);
166        assert_eq!(it.next(), None);
167    }
168}