1use crate::prelude::*;
2use std::str::FromStr;
3
4#[derive(Debug, Clone, PartialEq, Default, derive_more::Display)]
6pub enum HttpMethod {
7 #[display("PUT")]
8 #[default]
10 Put,
11 #[display("POST")]
12 Post,
14 #[display("PATCH")]
15 Patch,
17}
18
19#[derive(Debug, thiserror::Error)]
21#[error("无效的HTTP方法: {0}")]
22pub struct ParseHttpMethodError(String);
23
24impl FromStr for HttpMethod {
25 type Err = ParseHttpMethodError;
26
27 fn from_str(s: &str) -> Result<Self, Self::Err> {
28 match s.to_uppercase().as_str() {
29 "PUT" => Ok(HttpMethod::Put),
30 "POST" => Ok(HttpMethod::Post),
31 "PATCH" => Ok(HttpMethod::Patch),
32 _ => Err(ParseHttpMethodError(s.to_string())),
33 }
34 }
35}
36
37impl TryFrom<&str> for HttpMethod {
38 type Error = ParseHttpMethodError;
39
40 fn try_from(value: &str) -> Result<Self, Self::Error> {
41 HttpMethod::from_str(value)
42 }
43}
44
45impl TryFrom<String> for HttpMethod {
46 type Error = ParseHttpMethodError;
47
48 fn try_from(value: String) -> Result<Self, Self::Error> {
49 HttpMethod::from_str(&value)
50 }
51}
52
53#[derive(Clone, Debug, Default)]
55pub struct UploadOptions {
56 http_method: HttpMethod,
58 compression: bool,
60 metadata: ValueDict,
62}
63
64impl UploadOptions {
65 pub fn new() -> Self {
67 Self::default()
68 }
69
70 pub fn with_method(method: HttpMethod) -> Self {
72 Self {
73 http_method: method,
74 compression: false,
75 metadata: ValueDict::default(),
76 }
77 }
78
79 pub fn method(mut self, method: HttpMethod) -> Self {
81 self.http_method = method;
82 self
83 }
84
85 pub fn compression(mut self, enable: bool) -> Self {
87 self.compression = enable;
88 self
89 }
90
91 pub fn metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
94 self.metadata
95 .insert(key.into(), ValueType::String(value.into()));
96 self
97 }
98
99 pub fn http_method(&self) -> &HttpMethod {
101 &self.http_method
102 }
103
104 pub fn compression_enabled(&self) -> bool {
106 self.compression
107 }
108
109 pub fn metadata_dict(&self) -> &ValueDict {
111 &self.metadata
112 }
113
114 pub fn for_test() -> Self {
116 Self {
117 http_method: HttpMethod::Put,
118 compression: false,
119 metadata: ValueDict::default(),
120 }
121 }
122}
123
124impl From<(usize, ValueDict)> for UploadOptions {
125 fn from((method, values): (usize, ValueDict)) -> Self {
126 let http_method = match method {
127 0 => HttpMethod::Put,
128 1 => HttpMethod::Post,
129 2 => HttpMethod::Patch,
130 _ => HttpMethod::Put,
131 };
132
133 Self {
134 http_method,
135 compression: false,
136 metadata: values,
137 }
138 }
139}
140
141impl From<crate::update::DownloadOptions> for UploadOptions {
142 fn from(_: crate::update::DownloadOptions) -> Self {
143 Self::default()
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150 use std::str::FromStr;
151
152 #[test]
153 fn test_from_str_valid_cases() {
154 assert_eq!(HttpMethod::from_str("PUT").unwrap(), HttpMethod::Put);
155 assert_eq!(HttpMethod::from_str("put").unwrap(), HttpMethod::Put);
156 assert_eq!(HttpMethod::from_str("Put").unwrap(), HttpMethod::Put);
157
158 assert_eq!(HttpMethod::from_str("POST").unwrap(), HttpMethod::Post);
159 assert_eq!(HttpMethod::from_str("post").unwrap(), HttpMethod::Post);
160 assert_eq!(HttpMethod::from_str("Post").unwrap(), HttpMethod::Post);
161
162 assert_eq!(HttpMethod::from_str("PATCH").unwrap(), HttpMethod::Patch);
163 assert_eq!(HttpMethod::from_str("patch").unwrap(), HttpMethod::Patch);
164 assert_eq!(HttpMethod::from_str("Patch").unwrap(), HttpMethod::Patch);
165 }
166
167 #[test]
168 fn test_from_str_invalid_cases() {
169 assert!(HttpMethod::from_str("GET").is_err());
170 assert!(HttpMethod::from_str("DELETE").is_err());
171 assert!(HttpMethod::from_str("INVALID").is_err());
172 assert!(HttpMethod::from_str("").is_err());
173 assert!(HttpMethod::from_str(" PUT ").is_err()); }
175
176 #[test]
177 fn test_try_from_str() {
178 assert_eq!(HttpMethod::try_from("PUT").unwrap(), HttpMethod::Put);
179 assert_eq!(HttpMethod::try_from("Post").unwrap(), HttpMethod::Post);
180 assert_eq!(HttpMethod::try_from("patch").unwrap(), HttpMethod::Patch);
181 }
182
183 #[test]
184 fn test_try_from_string() {
185 assert_eq!(
186 HttpMethod::try_from(String::from("PUT")).unwrap(),
187 HttpMethod::Put
188 );
189 assert_eq!(
190 HttpMethod::try_from(String::from("POST")).unwrap(),
191 HttpMethod::Post
192 );
193 assert_eq!(
194 HttpMethod::try_from(String::from("PATCH")).unwrap(),
195 HttpMethod::Patch
196 );
197
198 assert!(HttpMethod::try_from(String::from("DELETE")).is_err());
199 assert!(HttpMethod::try_from(String::from("")).is_err());
200 }
201
202 #[test]
203 fn test_parse_http_method_error() {
204 let err = HttpMethod::from_str("INVALID").unwrap_err();
205 assert_eq!(err.to_string(), "无效的HTTP方法: INVALID");
206
207 let err = HttpMethod::from_str("").unwrap_err();
208 assert_eq!(err.to_string(), "无效的HTTP方法: ");
209 }
210
211 #[test]
212 fn test_http_method_display() {
213 assert_eq!(HttpMethod::Put.to_string(), "PUT");
214 assert_eq!(HttpMethod::Post.to_string(), "POST");
215 assert_eq!(HttpMethod::Patch.to_string(), "PATCH");
216 }
217
218 #[test]
219 fn test_http_method_default() {
220 let method = HttpMethod::default();
221 assert_eq!(method, HttpMethod::Put);
222 }
223
224 #[test]
225 fn test_http_method_clone() {
226 let original = HttpMethod::Post;
227 let cloned = original.clone();
228 assert_eq!(original, cloned);
229 }
230
231 #[test]
232 fn test_http_method_partial_eq() {
233 assert_eq!(HttpMethod::Put, HttpMethod::Put);
234 assert_ne!(HttpMethod::Put, HttpMethod::Post);
235 assert_ne!(HttpMethod::Post, HttpMethod::Patch);
236 assert_ne!(HttpMethod::Patch, HttpMethod::Put);
237 }
238
239 #[test]
240 fn test_upload_options_new() {
241 let options = UploadOptions::new();
242 assert_eq!(options.http_method(), &HttpMethod::Put);
243 assert!(!options.compression_enabled());
244 assert!(options.metadata_dict().is_empty());
245 }
246
247 #[test]
248 fn test_upload_options_default() {
249 let options = UploadOptions::default();
250 assert_eq!(options.http_method(), &HttpMethod::Put);
251 assert!(!options.compression_enabled());
252 assert!(options.metadata_dict().is_empty());
253 }
254
255 #[test]
256 fn test_upload_options_with_method() {
257 let options = UploadOptions::with_method(HttpMethod::Post);
258 assert_eq!(options.http_method(), &HttpMethod::Post);
259 assert!(!options.compression_enabled());
260 assert!(options.metadata_dict().is_empty());
261 }
262
263 #[test]
264 fn test_upload_options_method_setter() {
265 let options = UploadOptions::new().method(HttpMethod::Patch);
266 assert_eq!(options.http_method(), &HttpMethod::Patch);
267 }
268
269 #[test]
270 fn test_upload_options_compression() {
271 let options = UploadOptions::new().compression(true);
272 assert!(options.compression_enabled());
273
274 let options = options.compression(false);
275 assert!(!options.compression_enabled());
276 }
277
278 #[test]
279 fn test_upload_options_metadata() {
280 let options = UploadOptions::new()
281 .metadata("key1", "value1")
282 .metadata("key2", "value2");
283
284 let metadata = options.metadata_dict();
285 assert_eq!(metadata.len(), 2);
286 assert_eq!(
287 metadata.get("KEY1"),
288 Some(&ValueType::String("value1".to_string()))
289 );
290 assert_eq!(
291 metadata.get("KEY2"),
292 Some(&ValueType::String("value2".to_string()))
293 );
294 }
295
296 #[test]
297 fn test_upload_options_for_test() {
298 let options = UploadOptions::for_test();
299 assert_eq!(options.http_method(), &HttpMethod::Put);
300 assert!(!options.compression_enabled());
301 assert!(options.metadata_dict().is_empty());
302 }
303
304 #[test]
305 fn test_upload_options_getters() {
306 let options = UploadOptions::new()
307 .method(HttpMethod::Post)
308 .compression(true)
309 .metadata("test", "value");
310
311 assert_eq!(options.http_method(), &HttpMethod::Post);
312 assert!(options.compression_enabled());
313 assert_eq!(options.metadata_dict().len(), 1);
314 }
315
316 #[test]
317 fn test_upload_options_clone() {
318 let original = UploadOptions::new()
319 .method(HttpMethod::Patch)
320 .compression(true)
321 .metadata("clone", "test");
322
323 let cloned = original.clone();
324 assert_eq!(original.http_method(), cloned.http_method());
325 assert_eq!(original.compression_enabled(), cloned.compression_enabled());
326 assert_eq!(original.metadata_dict(), cloned.metadata_dict());
327 }
328
329 #[test]
330 fn test_upload_options_debug() {
331 let options = UploadOptions::new()
332 .method(HttpMethod::Post)
333 .compression(true)
334 .metadata("debug", "test");
335
336 let debug_str = format!("{options:?}");
337 assert!(debug_str.contains("UploadOptions"));
338 assert!(debug_str.contains("Post"));
339 assert!(debug_str.contains("true"));
340 }
341
342 #[test]
343 fn test_from_usize_value_dict() {
344 let mut metadata = ValueDict::new();
345 metadata.insert("test".to_string(), ValueType::String("value".to_string()));
346
347 let options: UploadOptions = (0, metadata.clone()).into();
348 assert_eq!(options.http_method(), &HttpMethod::Put);
349 assert_eq!(options.metadata_dict(), &metadata);
350
351 let options: UploadOptions = (1, metadata.clone()).into();
352 assert_eq!(options.http_method(), &HttpMethod::Post);
353
354 let options: UploadOptions = (2, metadata.clone()).into();
355 assert_eq!(options.http_method(), &HttpMethod::Patch);
356
357 let options: UploadOptions = (999, metadata.clone()).into();
358 assert_eq!(options.http_method(), &HttpMethod::Put); }
360
361 #[test]
362 fn test_from_download_options() {
363 let _ = UploadOptions::from(crate::update::DownloadOptions::default());
366 }
367
368 #[test]
369 fn test_upload_options_builder_pattern() {
370 let options = UploadOptions::new()
371 .method(HttpMethod::Post)
372 .compression(true)
373 .metadata("author", "test")
374 .metadata("version", "1.0");
375
376 assert_eq!(options.http_method(), &HttpMethod::Post);
377 assert!(options.compression_enabled());
378 assert_eq!(options.metadata_dict().len(), 2);
379 }
380
381 #[test]
382 fn test_upload_options_chaining() {
383 let base = UploadOptions::new();
384 let options1 = base.clone().method(HttpMethod::Patch);
385 let options2 = base.clone().compression(true);
386 let options3 = base.clone().metadata("key", "value");
387
388 assert_eq!(options1.http_method(), &HttpMethod::Patch);
389 assert!(!options1.compression_enabled());
390
391 assert_eq!(options2.http_method(), &HttpMethod::Put);
392 assert!(options2.compression_enabled());
393
394 assert_eq!(options3.http_method(), &HttpMethod::Put);
395 assert!(!options3.compression_enabled());
396 assert_eq!(options3.metadata_dict().len(), 1);
397 }
398}