1use std::fmt::{self, Display};
2use std::str::FromStr;
3use std::io::{Error, ErrorKind};
4
5#[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 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 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 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}