1use std::fmt;
3use std::str::FromStr;
4use std::convert::AsRef;
5
6use error::Error;
7use self::Method::{Options, Get, Post, Put, Delete, Head, Trace, Connect, Patch,
8 Extension};
9
10
11#[derive(Clone, PartialEq, Eq, Hash, Debug)]
20pub enum Method {
21 Options,
23 Get,
25 Post,
27 Put,
29 Delete,
31 Head,
33 Trace,
35 Connect,
37 Patch,
39 Extension(String)
41}
42
43impl AsRef<str> for Method {
44 fn as_ref(&self) -> &str {
45 match *self {
46 Options => "OPTIONS",
47 Get => "GET",
48 Post => "POST",
49 Put => "PUT",
50 Delete => "DELETE",
51 Head => "HEAD",
52 Trace => "TRACE",
53 Connect => "CONNECT",
54 Patch => "PATCH",
55 Extension(ref s) => s.as_ref()
56 }
57 }
58}
59
60impl Method {
61 pub fn safe(&self) -> bool {
67 match *self {
68 Get | Head | Options | Trace => true,
69 _ => false
70 }
71 }
72
73 pub fn idempotent(&self) -> bool {
79 if self.safe() {
80 true
81 } else {
82 match *self {
83 Put | Delete => true,
84 _ => false
85 }
86 }
87 }
88}
89
90impl FromStr for Method {
91 type Err = Error;
92 fn from_str(s: &str) -> Result<Method, Error> {
93 if s == "" {
94 Err(Error::Method)
95 } else {
96 Ok(match s {
97 "OPTIONS" => Options,
98 "GET" => Get,
99 "POST" => Post,
100 "PUT" => Put,
101 "DELETE" => Delete,
102 "HEAD" => Head,
103 "TRACE" => Trace,
104 "CONNECT" => Connect,
105 "PATCH" => Patch,
106 _ => Extension(s.to_owned())
107 })
108 }
109 }
110}
111
112impl fmt::Display for Method {
113 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
114 fmt.write_str(match *self {
115 Options => "OPTIONS",
116 Get => "GET",
117 Post => "POST",
118 Put => "PUT",
119 Delete => "DELETE",
120 Head => "HEAD",
121 Trace => "TRACE",
122 Connect => "CONNECT",
123 Patch => "PATCH",
124 Extension(ref s) => s.as_ref()
125 })
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use std::collections::HashMap;
132 use std::str::FromStr;
133 use error::Error;
134 use super::Method;
135 use super::Method::{Get, Post, Put, Extension};
136
137 #[test]
138 fn test_safe() {
139 assert_eq!(true, Get.safe());
140 assert_eq!(false, Post.safe());
141 }
142
143 #[test]
144 fn test_idempotent() {
145 assert_eq!(true, Get.idempotent());
146 assert_eq!(true, Put.idempotent());
147 assert_eq!(false, Post.idempotent());
148 }
149
150 #[test]
151 fn test_from_str() {
152 assert_eq!(Get, FromStr::from_str("GET").unwrap());
153 assert_eq!(Extension("MOVE".to_owned()),
154 FromStr::from_str("MOVE").unwrap());
155 let x: Result<Method, _> = FromStr::from_str("");
156 if let Err(Error::Method) = x {
157 } else {
158 panic!("An empty method is invalid!")
159 }
160 }
161
162 #[test]
163 fn test_fmt() {
164 assert_eq!("GET".to_owned(), format!("{}", Get));
165 assert_eq!("MOVE".to_owned(),
166 format!("{}", Extension("MOVE".to_owned())));
167 }
168
169 #[test]
170 fn test_hashable() {
171 let mut counter: HashMap<Method,usize> = HashMap::new();
172 counter.insert(Get, 1);
173 assert_eq!(Some(&1), counter.get(&Get));
174 }
175
176 #[test]
177 fn test_as_str() {
178 assert_eq!(Get.as_ref(), "GET");
179 assert_eq!(Post.as_ref(), "POST");
180 assert_eq!(Put.as_ref(), "PUT");
181 assert_eq!(Extension("MOVE".to_owned()).as_ref(), "MOVE");
182 }
183}