async_httplib/
method.rs

1use std::fmt::{self, Display};
2use std::str::FromStr;
3use std::io::{Error, ErrorKind};
4
5/// [Read more](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
6#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
7pub enum Method {
8    Get,
9    Head,
10    Post,
11    Put,
12    Delete,
13    Connect,
14    Options,
15    Trace,
16    Patch,
17}
18
19impl Method {
20
21    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.1) for more details.
22    pub fn is_safe(&self) -> bool {
23        match self {
24            Method::Get | Method::Head | Method::Options | Method::Trace => true,
25            _ => false,
26        }
27    }
28
29    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.2) for more details.
30    pub fn is_idempotent(&self) -> bool {
31        match self {
32            Method::Get | Method::Head | Method::Options | Method::Trace | Method::Put | Method::Delete => true,
33            _ => false,
34        }
35    }
36
37    /// See [the spec](https://tools.ietf.org/html/rfc7231#section-4.2.3) for more details.
38    pub fn is_cacheable(&self) -> bool {
39        match self {
40            Method::Get | Method::Head => true,
41            _ => false,
42        }
43    }
44
45    pub fn has_body(&self) -> bool {
46        match self {
47            Method::Post | Method::Put | Method::Delete | Method::Patch => true,
48            _ => false,
49        }
50    }
51}
52
53impl Display for Method {
54
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        match self {
57            Self::Get => write!(f, "GET"),
58            Self::Head => write!(f, "HEAD"),
59            Self::Post => write!(f, "POST"),
60            Self::Put => write!(f, "PUT"),
61            Self::Delete => write!(f, "DELETE"),
62            Self::Connect => write!(f, "CONNECT"),
63            Self::Options => write!(f, "OPTIONS"),
64            Self::Trace => write!(f, "TRACE"),
65            Self::Patch => write!(f, "PATCH"),
66        }
67    }
68}
69
70impl FromStr for Method {
71    type Err = Error;
72
73    fn from_str(s: &str) -> Result<Self, Self::Err> {
74        match s {
75            "GET" => Ok(Self::Get),
76            "HEAD" => Ok(Self::Head),
77            "POST" => Ok(Self::Post),
78            "PUT" => Ok(Self::Put),
79            "DELETE" => Ok(Self::Delete),
80            "CONNECT" => Ok(Self::Connect),
81            "OPTIONS" => Ok(Self::Options),
82            "TRACE" => Ok(Self::Trace),
83            "PATCH" => Ok(Self::Patch),
84            s => Err(Error::new(ErrorKind::InvalidInput, format!("The method `{}` is invalid.", s))),
85        }
86    }
87}
88
89impl<'a> std::convert::TryFrom<&[u8]> for Method {
90    type Error = Error;
91
92    fn try_from(bytes: &[u8]) -> Result<Self, Self::Error> {
93        match String::from_utf8(bytes.to_vec()) {
94            Ok(txt) => Self::from_str(&txt),
95            Err(e) => Err(Error::new(ErrorKind::InvalidInput, e.to_string())),
96        }
97    }
98}
99
100#[cfg(test)]
101mod tests {
102    use super::*;
103    use std::convert::TryFrom;
104
105    #[test]
106    fn implements_from_str() {
107        let method = Method::from_str("POST").unwrap();
108        assert_eq!(method, Method::Post);
109    }
110
111    #[test]
112    fn implements_try_from() {
113        let method = Method::try_from("POST".as_bytes()).unwrap();
114        assert_eq!(method, Method::Post);
115    }
116
117    #[test]
118    fn implements_to_string() {
119        let method = Method::from_str("POST").unwrap();
120        assert_eq!(method.to_string(), "POST");
121    }
122}