no_std_http/
method.rs

1use strum::{AsRefStr, Display, EnumIter, EnumString};
2/// The Request Method (VERB)
3///
4/// This type also contains constants for a number of common HTTP methods such
5/// as GET, POST, etc.
6///
7/// Currently includes 8 variants representing the 8 methods defined in
8/// [RFC 7230](https://tools.ietf.org/html/rfc7231#section-4.1), plus PATCH.
9///
10/// # Examples
11///
12/// ```
13/// use http::Method;
14/// use std::str::FromStr;
15///
16/// assert_eq!(Method::Get, Method::from_str("GET").unwrap());
17/// assert!(Method::Get.is_idempotent());
18/// assert_eq!(Method::Post.as_ref(), "POST");
19/// ```
20#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, AsRefStr, Display, EnumString, EnumIter)]
21#[strum(ascii_case_insensitive, serialize_all = "UPPERCASE")]
22pub enum Method {
23    Options,
24    #[default]
25    Get,
26    Post,
27    Put,
28    Delete,
29    Head,
30    Trace,
31    Connect,
32    Patch,
33}
34
35impl Method {
36    /// Whether a method is considered "safe", meaning the request is
37    /// essentially read-only.
38    ///
39    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.1)
40    /// for more words.
41    pub fn is_safe(&self) -> bool {
42        use Method::*;
43        matches!(self, Get | Head | Options | Trace)
44    }
45
46    /// Whether a method is considered "idempotent", meaning the request has
47    /// the same result if executed multiple times.
48    ///
49    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.2) for
50    /// more words.
51    pub fn is_idempotent(&self) -> bool {
52        use Method::*;
53        match self {
54            Put | Delete => true,
55            _ => self.is_safe(),
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use core::str::FromStr;
63
64    use strum::IntoEnumIterator;
65
66    use super::*;
67
68    #[test]
69    fn test_enum_string() {
70        for method in Method::iter() {
71            let str = method.as_ref();
72            assert_eq!(Method::from_str(str).unwrap(), method);
73        }
74    }
75
76    #[test]
77    fn test_is_idempotent() {
78        assert!(Method::Options.is_idempotent());
79        assert!(Method::Get.is_idempotent());
80        assert!(Method::Put.is_idempotent());
81        assert!(Method::Delete.is_idempotent());
82        assert!(Method::Head.is_idempotent());
83        assert!(Method::Trace.is_idempotent());
84
85        assert!(!Method::Post.is_idempotent());
86        assert!(!Method::Connect.is_idempotent());
87        assert!(!Method::Patch.is_idempotent());
88    }
89}