1use std::error;
2use std::ffi::{self, CStr};
3use std::fmt;
4use std::io;
5use std::str;
6
7#[derive(Clone, PartialEq)]
11pub struct Error {
12 code: curl_sys::CURLcode,
13 extra: Option<Box<str>>,
14}
15
16impl Error {
17 pub fn new(code: curl_sys::CURLcode) -> Error {
19 Error { code, extra: None }
20 }
21
22 pub fn set_extra(&mut self, extra: String) {
28 self.extra = Some(extra.into());
29 }
30
31 pub fn is_unsupported_protocol(&self) -> bool {
33 self.code == curl_sys::CURLE_UNSUPPORTED_PROTOCOL
34 }
35
36 pub fn is_failed_init(&self) -> bool {
38 self.code == curl_sys::CURLE_FAILED_INIT
39 }
40
41 pub fn is_url_malformed(&self) -> bool {
43 self.code == curl_sys::CURLE_URL_MALFORMAT
44 }
45
46 pub fn is_couldnt_resolve_proxy(&self) -> bool {
53 self.code == curl_sys::CURLE_COULDNT_RESOLVE_PROXY
54 }
55
56 pub fn is_couldnt_resolve_host(&self) -> bool {
58 self.code == curl_sys::CURLE_COULDNT_RESOLVE_HOST
59 }
60
61 pub fn is_couldnt_connect(&self) -> bool {
63 self.code == curl_sys::CURLE_COULDNT_CONNECT
64 }
65
66 pub fn is_remote_access_denied(&self) -> bool {
68 self.code == curl_sys::CURLE_REMOTE_ACCESS_DENIED
69 }
70
71 pub fn is_partial_file(&self) -> bool {
73 self.code == curl_sys::CURLE_PARTIAL_FILE
74 }
75
76 pub fn is_quote_error(&self) -> bool {
78 self.code == curl_sys::CURLE_QUOTE_ERROR
79 }
80
81 pub fn is_http_returned_error(&self) -> bool {
83 self.code == curl_sys::CURLE_HTTP_RETURNED_ERROR
84 }
85
86 pub fn is_read_error(&self) -> bool {
88 self.code == curl_sys::CURLE_READ_ERROR
89 }
90
91 pub fn is_write_error(&self) -> bool {
93 self.code == curl_sys::CURLE_WRITE_ERROR
94 }
95
96 pub fn is_upload_failed(&self) -> bool {
98 self.code == curl_sys::CURLE_UPLOAD_FAILED
99 }
100
101 pub fn is_out_of_memory(&self) -> bool {
103 self.code == curl_sys::CURLE_OUT_OF_MEMORY
104 }
105
106 pub fn is_operation_timedout(&self) -> bool {
108 self.code == curl_sys::CURLE_OPERATION_TIMEDOUT
109 }
110
111 pub fn is_range_error(&self) -> bool {
113 self.code == curl_sys::CURLE_RANGE_ERROR
114 }
115
116 pub fn is_http_post_error(&self) -> bool {
118 self.code == curl_sys::CURLE_HTTP_POST_ERROR
119 }
120
121 pub fn is_ssl_connect_error(&self) -> bool {
123 self.code == curl_sys::CURLE_SSL_CONNECT_ERROR
124 }
125
126 pub fn is_bad_download_resume(&self) -> bool {
128 self.code == curl_sys::CURLE_BAD_DOWNLOAD_RESUME
129 }
130
131 pub fn is_file_couldnt_read_file(&self) -> bool {
133 self.code == curl_sys::CURLE_FILE_COULDNT_READ_FILE
134 }
135
136 pub fn is_function_not_found(&self) -> bool {
138 self.code == curl_sys::CURLE_FUNCTION_NOT_FOUND
139 }
140
141 pub fn is_aborted_by_callback(&self) -> bool {
143 self.code == curl_sys::CURLE_ABORTED_BY_CALLBACK
144 }
145
146 pub fn is_bad_function_argument(&self) -> bool {
148 self.code == curl_sys::CURLE_BAD_FUNCTION_ARGUMENT
149 }
150
151 pub fn is_interface_failed(&self) -> bool {
153 self.code == curl_sys::CURLE_INTERFACE_FAILED
154 }
155
156 pub fn is_too_many_redirects(&self) -> bool {
158 self.code == curl_sys::CURLE_TOO_MANY_REDIRECTS
159 }
160
161 pub fn is_unknown_option(&self) -> bool {
163 self.code == curl_sys::CURLE_UNKNOWN_OPTION
164 }
165
166 pub fn is_peer_failed_verification(&self) -> bool {
168 self.code == curl_sys::CURLE_PEER_FAILED_VERIFICATION
169 }
170
171 pub fn is_got_nothing(&self) -> bool {
173 self.code == curl_sys::CURLE_GOT_NOTHING
174 }
175
176 pub fn is_ssl_engine_notfound(&self) -> bool {
178 self.code == curl_sys::CURLE_SSL_ENGINE_NOTFOUND
179 }
180
181 pub fn is_ssl_engine_setfailed(&self) -> bool {
183 self.code == curl_sys::CURLE_SSL_ENGINE_SETFAILED
184 }
185
186 pub fn is_send_error(&self) -> bool {
188 self.code == curl_sys::CURLE_SEND_ERROR
189 }
190
191 pub fn is_recv_error(&self) -> bool {
193 self.code == curl_sys::CURLE_RECV_ERROR
194 }
195
196 pub fn is_ssl_certproblem(&self) -> bool {
198 self.code == curl_sys::CURLE_SSL_CERTPROBLEM
199 }
200
201 pub fn is_ssl_cipher(&self) -> bool {
203 self.code == curl_sys::CURLE_SSL_CIPHER
204 }
205
206 pub fn is_ssl_cacert(&self) -> bool {
208 self.code == curl_sys::CURLE_SSL_CACERT
209 }
210
211 pub fn is_bad_content_encoding(&self) -> bool {
213 self.code == curl_sys::CURLE_BAD_CONTENT_ENCODING
214 }
215
216 pub fn is_filesize_exceeded(&self) -> bool {
218 self.code == curl_sys::CURLE_FILESIZE_EXCEEDED
219 }
220
221 pub fn is_use_ssl_failed(&self) -> bool {
223 self.code == curl_sys::CURLE_USE_SSL_FAILED
224 }
225
226 pub fn is_send_fail_rewind(&self) -> bool {
228 self.code == curl_sys::CURLE_SEND_FAIL_REWIND
229 }
230
231 pub fn is_ssl_engine_initfailed(&self) -> bool {
233 self.code == curl_sys::CURLE_SSL_ENGINE_INITFAILED
234 }
235
236 pub fn is_login_denied(&self) -> bool {
238 self.code == curl_sys::CURLE_LOGIN_DENIED
239 }
240
241 pub fn is_conv_failed(&self) -> bool {
243 self.code == curl_sys::CURLE_CONV_FAILED
244 }
245
246 pub fn is_conv_required(&self) -> bool {
248 self.code == curl_sys::CURLE_CONV_REQD
249 }
250
251 pub fn is_ssl_cacert_badfile(&self) -> bool {
253 self.code == curl_sys::CURLE_SSL_CACERT_BADFILE
254 }
255
256 pub fn is_ssl_crl_badfile(&self) -> bool {
258 self.code == curl_sys::CURLE_SSL_CRL_BADFILE
259 }
260
261 pub fn is_ssl_shutdown_failed(&self) -> bool {
263 self.code == curl_sys::CURLE_SSL_SHUTDOWN_FAILED
264 }
265
266 pub fn is_again(&self) -> bool {
268 self.code == curl_sys::CURLE_AGAIN
269 }
270
271 pub fn is_ssl_issuer_error(&self) -> bool {
273 self.code == curl_sys::CURLE_SSL_ISSUER_ERROR
274 }
275
276 pub fn is_chunk_failed(&self) -> bool {
278 self.code == curl_sys::CURLE_CHUNK_FAILED
279 }
280
281 pub fn is_http2_error(&self) -> bool {
283 self.code == curl_sys::CURLE_HTTP2
284 }
285
286 pub fn is_http2_stream_error(&self) -> bool {
288 self.code == curl_sys::CURLE_HTTP2_STREAM
289 }
290
291 pub fn code(&self) -> curl_sys::CURLcode {
298 self.code
299 }
300
301 pub fn description(&self) -> &str {
304 unsafe {
305 let s = curl_sys::curl_easy_strerror(self.code);
306 assert!(!s.is_null());
307 str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
308 }
309 }
310
311 pub fn extra_description(&self) -> Option<&str> {
313 self.extra.as_deref()
314 }
315}
316
317impl fmt::Display for Error {
318 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
319 let desc = self.description();
320 match self.extra {
321 Some(ref s) => write!(f, "[{}] {} ({})", self.code(), desc, s),
322 None => write!(f, "[{}] {}", self.code(), desc),
323 }
324 }
325}
326
327impl fmt::Debug for Error {
328 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
329 f.debug_struct("Error")
330 .field("description", &self.description())
331 .field("code", &self.code)
332 .field("extra", &self.extra)
333 .finish()
334 }
335}
336
337impl error::Error for Error {}
338
339#[derive(Clone, PartialEq)]
343pub struct ShareError {
344 code: curl_sys::CURLSHcode,
345}
346
347impl ShareError {
348 pub fn new(code: curl_sys::CURLSHcode) -> ShareError {
350 ShareError { code }
351 }
352
353 pub fn is_bad_option(&self) -> bool {
355 self.code == curl_sys::CURLSHE_BAD_OPTION
356 }
357
358 pub fn is_in_use(&self) -> bool {
360 self.code == curl_sys::CURLSHE_IN_USE
361 }
362
363 pub fn is_invalid(&self) -> bool {
365 self.code == curl_sys::CURLSHE_INVALID
366 }
367
368 pub fn is_nomem(&self) -> bool {
370 self.code == curl_sys::CURLSHE_NOMEM
371 }
372
373 pub fn code(&self) -> curl_sys::CURLSHcode {
380 self.code
381 }
382
383 pub fn description(&self) -> &str {
385 unsafe {
386 let s = curl_sys::curl_share_strerror(self.code);
387 assert!(!s.is_null());
388 str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
389 }
390 }
391}
392
393impl fmt::Display for ShareError {
394 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
395 self.description().fmt(f)
396 }
397}
398
399impl fmt::Debug for ShareError {
400 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
401 write!(
402 f,
403 "ShareError {{ description: {:?}, code: {} }}",
404 self.description(),
405 self.code
406 )
407 }
408}
409
410impl error::Error for ShareError {}
411
412#[derive(Clone, PartialEq)]
416pub struct MultiError {
417 code: curl_sys::CURLMcode,
418}
419
420impl MultiError {
421 pub fn new(code: curl_sys::CURLMcode) -> MultiError {
423 MultiError { code }
424 }
425
426 pub fn is_bad_handle(&self) -> bool {
428 self.code == curl_sys::CURLM_BAD_HANDLE
429 }
430
431 pub fn is_bad_easy_handle(&self) -> bool {
433 self.code == curl_sys::CURLM_BAD_EASY_HANDLE
434 }
435
436 pub fn is_out_of_memory(&self) -> bool {
438 self.code == curl_sys::CURLM_OUT_OF_MEMORY
439 }
440
441 pub fn is_internal_error(&self) -> bool {
443 self.code == curl_sys::CURLM_INTERNAL_ERROR
444 }
445
446 pub fn is_bad_socket(&self) -> bool {
448 self.code == curl_sys::CURLM_BAD_SOCKET
449 }
450
451 pub fn is_unknown_option(&self) -> bool {
453 self.code == curl_sys::CURLM_UNKNOWN_OPTION
454 }
455
456 pub fn is_call_perform(&self) -> bool {
458 self.code == curl_sys::CURLM_CALL_MULTI_PERFORM
459 }
460
461 pub fn code(&self) -> curl_sys::CURLMcode {
468 self.code
469 }
470
471 pub fn description(&self) -> &str {
473 unsafe {
474 let s = curl_sys::curl_multi_strerror(self.code);
475 assert!(!s.is_null());
476 str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
477 }
478 }
479}
480
481impl fmt::Display for MultiError {
482 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
483 self.description().fmt(f)
484 }
485}
486
487impl fmt::Debug for MultiError {
488 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
489 f.debug_struct("MultiError")
490 .field("description", &self.description())
491 .field("code", &self.code)
492 .finish()
493 }
494}
495
496impl error::Error for MultiError {}
497
498#[derive(Clone, PartialEq)]
502pub struct FormError {
503 code: curl_sys::CURLFORMcode,
504}
505
506impl FormError {
507 pub fn new(code: curl_sys::CURLFORMcode) -> FormError {
509 FormError { code }
510 }
511
512 pub fn is_memory(&self) -> bool {
514 self.code == curl_sys::CURL_FORMADD_MEMORY
515 }
516
517 pub fn is_option_twice(&self) -> bool {
519 self.code == curl_sys::CURL_FORMADD_OPTION_TWICE
520 }
521
522 pub fn is_null(&self) -> bool {
524 self.code == curl_sys::CURL_FORMADD_NULL
525 }
526
527 pub fn is_unknown_option(&self) -> bool {
529 self.code == curl_sys::CURL_FORMADD_UNKNOWN_OPTION
530 }
531
532 pub fn is_incomplete(&self) -> bool {
534 self.code == curl_sys::CURL_FORMADD_INCOMPLETE
535 }
536
537 pub fn is_illegal_array(&self) -> bool {
539 self.code == curl_sys::CURL_FORMADD_ILLEGAL_ARRAY
540 }
541
542 pub fn is_disabled(&self) -> bool {
544 self.code == curl_sys::CURL_FORMADD_DISABLED
545 }
546
547 pub fn code(&self) -> curl_sys::CURLFORMcode {
549 self.code
550 }
551
552 pub fn description(&self) -> &str {
554 match self.code {
555 curl_sys::CURL_FORMADD_MEMORY => "allocation failure",
556 curl_sys::CURL_FORMADD_OPTION_TWICE => "one option passed twice",
557 curl_sys::CURL_FORMADD_NULL => "null pointer given for string",
558 curl_sys::CURL_FORMADD_UNKNOWN_OPTION => "unknown option",
559 curl_sys::CURL_FORMADD_INCOMPLETE => "form information not complete",
560 curl_sys::CURL_FORMADD_ILLEGAL_ARRAY => "illegal array in option",
561 curl_sys::CURL_FORMADD_DISABLED => {
562 "libcurl does not have support for this option compiled in"
563 }
564 _ => "unknown form error",
565 }
566 }
567}
568
569impl fmt::Display for FormError {
570 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
571 self.description().fmt(f)
572 }
573}
574
575impl fmt::Debug for FormError {
576 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
577 f.debug_struct("FormError")
578 .field("description", &self.description())
579 .field("code", &self.code)
580 .finish()
581 }
582}
583
584impl error::Error for FormError {}
585
586impl From<ffi::NulError> for Error {
587 fn from(_: ffi::NulError) -> Error {
588 Error {
589 code: curl_sys::CURLE_CONV_FAILED,
590 extra: None,
591 }
592 }
593}
594
595impl From<Error> for io::Error {
596 fn from(e: Error) -> io::Error {
597 io::Error::new(io::ErrorKind::Other, e)
598 }
599}
600
601impl From<ShareError> for io::Error {
602 fn from(e: ShareError) -> io::Error {
603 io::Error::new(io::ErrorKind::Other, e)
604 }
605}
606
607impl From<MultiError> for io::Error {
608 fn from(e: MultiError) -> io::Error {
609 io::Error::new(io::ErrorKind::Other, e)
610 }
611}
612
613impl From<FormError> for io::Error {
614 fn from(e: FormError) -> io::Error {
615 io::Error::new(io::ErrorKind::Other, e)
616 }
617}