blob: f3b7c6f01d36d647cafbf7f6f3e8218ddca96e81 [file] [log] [blame]
use std::error;
use std::ffi::{self, CStr};
use std::fmt;
use std::str;
use std::io;
use curl_sys;
/// An error returned from various "easy" operations.
///
/// This structure wraps a `CURLcode`.
#[derive(Clone, PartialEq)]
pub struct Error {
code: curl_sys::CURLcode,
extra: Option<Box<str>>,
}
impl Error {
/// Creates a new error from the underlying code returned by libcurl.
pub fn new(code: curl_sys::CURLcode) -> Error {
Error {
code: code,
extra: None,
}
}
/// Stores some extra information about this error inside this error.
///
/// This is typically used with `take_error_buf` on the easy handles to
/// couple the extra `CURLOPT_ERRORBUFFER` information with an `Error` being
/// returned.
pub fn set_extra(&mut self, extra: String) {
self.extra = Some(extra.into());
}
/// Returns whether this error corresponds to CURLE_UNSUPPORTED_PROTOCOL.
pub fn is_unsupported_protocol(&self) -> bool {
self.code == curl_sys::CURLE_UNSUPPORTED_PROTOCOL
}
/// Returns whether this error corresponds to CURLE_FAILED_INIT.
pub fn is_failed_init(&self) -> bool {
self.code == curl_sys::CURLE_FAILED_INIT
}
/// Returns whether this error corresponds to CURLE_URL_MALFORMAT.
pub fn is_url_malformed(&self) -> bool {
self.code == curl_sys::CURLE_URL_MALFORMAT
}
// /// Returns whether this error corresponds to CURLE_NOT_BUILT_IN.
// pub fn is_not_built_in(&self) -> bool {
// self.code == curl_sys::CURLE_NOT_BUILT_IN
// }
/// Returns whether this error corresponds to CURLE_COULDNT_RESOLVE_PROXY.
pub fn is_couldnt_resolve_proxy(&self) -> bool {
self.code == curl_sys::CURLE_COULDNT_RESOLVE_PROXY
}
/// Returns whether this error corresponds to CURLE_COULDNT_RESOLVE_HOST.
pub fn is_couldnt_resolve_host(&self) -> bool {
self.code == curl_sys::CURLE_COULDNT_RESOLVE_HOST
}
/// Returns whether this error corresponds to CURLE_COULDNT_CONNECT.
pub fn is_couldnt_connect(&self) -> bool {
self.code == curl_sys::CURLE_COULDNT_CONNECT
}
/// Returns whether this error corresponds to CURLE_REMOTE_ACCESS_DENIED.
pub fn is_remote_access_denied(&self) -> bool {
self.code == curl_sys::CURLE_REMOTE_ACCESS_DENIED
}
/// Returns whether this error corresponds to CURLE_PARTIAL_FILE.
pub fn is_partial_file(&self) -> bool {
self.code == curl_sys::CURLE_PARTIAL_FILE
}
/// Returns whether this error corresponds to CURLE_QUOTE_ERROR.
pub fn is_quote_error(&self) -> bool {
self.code == curl_sys::CURLE_QUOTE_ERROR
}
/// Returns whether this error corresponds to CURLE_HTTP_RETURNED_ERROR.
pub fn is_http_returned_error(&self) -> bool {
self.code == curl_sys::CURLE_HTTP_RETURNED_ERROR
}
/// Returns whether this error corresponds to CURLE_READ_ERROR.
pub fn is_read_error(&self) -> bool {
self.code == curl_sys::CURLE_READ_ERROR
}
/// Returns whether this error corresponds to CURLE_WRITE_ERROR.
pub fn is_write_error(&self) -> bool {
self.code == curl_sys::CURLE_WRITE_ERROR
}
/// Returns whether this error corresponds to CURLE_UPLOAD_FAILED.
pub fn is_upload_failed(&self) -> bool {
self.code == curl_sys::CURLE_UPLOAD_FAILED
}
/// Returns whether this error corresponds to CURLE_OUT_OF_MEMORY.
pub fn is_out_of_memory(&self) -> bool {
self.code == curl_sys::CURLE_OUT_OF_MEMORY
}
/// Returns whether this error corresponds to CURLE_OPERATION_TIMEDOUT.
pub fn is_operation_timedout(&self) -> bool {
self.code == curl_sys::CURLE_OPERATION_TIMEDOUT
}
/// Returns whether this error corresponds to CURLE_RANGE_ERROR.
pub fn is_range_error(&self) -> bool {
self.code == curl_sys::CURLE_RANGE_ERROR
}
/// Returns whether this error corresponds to CURLE_HTTP_POST_ERROR.
pub fn is_http_post_error(&self) -> bool {
self.code == curl_sys::CURLE_HTTP_POST_ERROR
}
/// Returns whether this error corresponds to CURLE_SSL_CONNECT_ERROR.
pub fn is_ssl_connect_error(&self) -> bool {
self.code == curl_sys::CURLE_SSL_CONNECT_ERROR
}
/// Returns whether this error corresponds to CURLE_BAD_DOWNLOAD_RESUME.
pub fn is_bad_download_resume(&self) -> bool {
self.code == curl_sys::CURLE_BAD_DOWNLOAD_RESUME
}
/// Returns whether this error corresponds to CURLE_FILE_COULDNT_READ_FILE.
pub fn is_file_couldnt_read_file(&self) -> bool {
self.code == curl_sys::CURLE_FILE_COULDNT_READ_FILE
}
/// Returns whether this error corresponds to CURLE_FUNCTION_NOT_FOUND.
pub fn is_function_not_found(&self) -> bool {
self.code == curl_sys::CURLE_FUNCTION_NOT_FOUND
}
/// Returns whether this error corresponds to CURLE_ABORTED_BY_CALLBACK.
pub fn is_aborted_by_callback(&self) -> bool {
self.code == curl_sys::CURLE_ABORTED_BY_CALLBACK
}
/// Returns whether this error corresponds to CURLE_BAD_FUNCTION_ARGUMENT.
pub fn is_bad_function_argument(&self) -> bool {
self.code == curl_sys::CURLE_BAD_FUNCTION_ARGUMENT
}
/// Returns whether this error corresponds to CURLE_INTERFACE_FAILED.
pub fn is_interface_failed(&self) -> bool {
self.code == curl_sys::CURLE_INTERFACE_FAILED
}
/// Returns whether this error corresponds to CURLE_TOO_MANY_REDIRECTS.
pub fn is_too_many_redirects(&self) -> bool {
self.code == curl_sys::CURLE_TOO_MANY_REDIRECTS
}
/// Returns whether this error corresponds to CURLE_UNKNOWN_OPTION.
pub fn is_unknown_option(&self) -> bool {
self.code == curl_sys::CURLE_UNKNOWN_OPTION
}
/// Returns whether this error corresponds to CURLE_PEER_FAILED_VERIFICATION.
pub fn is_peer_failed_verification(&self) -> bool {
self.code == curl_sys::CURLE_PEER_FAILED_VERIFICATION
}
/// Returns whether this error corresponds to CURLE_GOT_NOTHING.
pub fn is_got_nothing(&self) -> bool {
self.code == curl_sys::CURLE_GOT_NOTHING
}
/// Returns whether this error corresponds to CURLE_SSL_ENGINE_NOTFOUND.
pub fn is_ssl_engine_notfound(&self) -> bool {
self.code == curl_sys::CURLE_SSL_ENGINE_NOTFOUND
}
/// Returns whether this error corresponds to CURLE_SSL_ENGINE_SETFAILED.
pub fn is_ssl_engine_setfailed(&self) -> bool {
self.code == curl_sys::CURLE_SSL_ENGINE_SETFAILED
}
/// Returns whether this error corresponds to CURLE_SEND_ERROR.
pub fn is_send_error(&self) -> bool {
self.code == curl_sys::CURLE_SEND_ERROR
}
/// Returns whether this error corresponds to CURLE_RECV_ERROR.
pub fn is_recv_error(&self) -> bool {
self.code == curl_sys::CURLE_RECV_ERROR
}
/// Returns whether this error corresponds to CURLE_SSL_CERTPROBLEM.
pub fn is_ssl_certproblem(&self) -> bool {
self.code == curl_sys::CURLE_SSL_CERTPROBLEM
}
/// Returns whether this error corresponds to CURLE_SSL_CIPHER.
pub fn is_ssl_cipher(&self) -> bool {
self.code == curl_sys::CURLE_SSL_CIPHER
}
/// Returns whether this error corresponds to CURLE_SSL_CACERT.
pub fn is_ssl_cacert(&self) -> bool {
self.code == curl_sys::CURLE_SSL_CACERT
}
/// Returns whether this error corresponds to CURLE_BAD_CONTENT_ENCODING.
pub fn is_bad_content_encoding(&self) -> bool {
self.code == curl_sys::CURLE_BAD_CONTENT_ENCODING
}
/// Returns whether this error corresponds to CURLE_FILESIZE_EXCEEDED.
pub fn is_filesize_exceeded(&self) -> bool {
self.code == curl_sys::CURLE_FILESIZE_EXCEEDED
}
/// Returns whether this error corresponds to CURLE_USE_SSL_FAILED.
pub fn is_use_ssl_failed(&self) -> bool {
self.code == curl_sys::CURLE_USE_SSL_FAILED
}
/// Returns whether this error corresponds to CURLE_SEND_FAIL_REWIND.
pub fn is_send_fail_rewind(&self) -> bool {
self.code == curl_sys::CURLE_SEND_FAIL_REWIND
}
/// Returns whether this error corresponds to CURLE_SSL_ENGINE_INITFAILED.
pub fn is_ssl_engine_initfailed(&self) -> bool {
self.code == curl_sys::CURLE_SSL_ENGINE_INITFAILED
}
/// Returns whether this error corresponds to CURLE_LOGIN_DENIED.
pub fn is_login_denied(&self) -> bool {
self.code == curl_sys::CURLE_LOGIN_DENIED
}
/// Returns whether this error corresponds to CURLE_CONV_FAILED.
pub fn is_conv_failed(&self) -> bool {
self.code == curl_sys::CURLE_CONV_FAILED
}
/// Returns whether this error corresponds to CURLE_CONV_REQD.
pub fn is_conv_required(&self) -> bool {
self.code == curl_sys::CURLE_CONV_REQD
}
/// Returns whether this error corresponds to CURLE_SSL_CACERT_BADFILE.
pub fn is_ssl_cacert_badfile(&self) -> bool {
self.code == curl_sys::CURLE_SSL_CACERT_BADFILE
}
/// Returns whether this error corresponds to CURLE_SSL_CRL_BADFILE.
pub fn is_ssl_crl_badfile(&self) -> bool {
self.code == curl_sys::CURLE_SSL_CRL_BADFILE
}
/// Returns whether this error corresponds to CURLE_SSL_SHUTDOWN_FAILED.
pub fn is_ssl_shutdown_failed(&self) -> bool {
self.code == curl_sys::CURLE_SSL_SHUTDOWN_FAILED
}
/// Returns whether this error corresponds to CURLE_AGAIN.
pub fn is_again(&self) -> bool {
self.code == curl_sys::CURLE_AGAIN
}
/// Returns whether this error corresponds to CURLE_SSL_ISSUER_ERROR.
pub fn is_ssl_issuer_error(&self) -> bool {
self.code == curl_sys::CURLE_SSL_ISSUER_ERROR
}
/// Returns whether this error corresponds to CURLE_CHUNK_FAILED.
pub fn is_chunk_failed(&self) -> bool {
self.code == curl_sys::CURLE_CHUNK_FAILED
}
// /// Returns whether this error corresponds to CURLE_NO_CONNECTION_AVAILABLE.
// pub fn is_no_connection_available(&self) -> bool {
// self.code == curl_sys::CURLE_NO_CONNECTION_AVAILABLE
// }
/// Returns the value of the underlying error corresponding to libcurl.
pub fn code(&self) -> curl_sys::CURLcode {
self.code
}
/// Returns the extra description of this error, if any is available.
pub fn extra_description(&self) -> Option<&str> {
self.extra.as_ref().map(|s| &**s)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let desc = error::Error::description(self);
match self.extra {
Some(ref s) => write!(f, "[{}] {} ({})", self.code(), desc, s),
None => write!(f, "[{}] {}", self.code(), desc),
}
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Error")
.field("description", &error::Error::description(self))
.field("code", &self.code)
.field("extra", &self.extra)
.finish()
}
}
impl error::Error for Error {
fn description(&self) -> &str {
unsafe {
let s = curl_sys::curl_easy_strerror(self.code);
assert!(!s.is_null());
str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
}
}
}
/// An error returned from "share" operations.
///
/// This structure wraps a `CURLSHcode`.
#[derive(Clone, PartialEq)]
pub struct ShareError {
code: curl_sys::CURLSHcode,
}
impl ShareError {
/// Creates a new error from the underlying code returned by libcurl.
pub fn new(code: curl_sys::CURLSHcode) -> ShareError {
ShareError { code: code }
}
/// Returns whether this error corresponds to CURLSHE_BAD_OPTION.
pub fn is_bad_option(&self) -> bool {
self.code == curl_sys::CURLSHE_BAD_OPTION
}
/// Returns whether this error corresponds to CURLSHE_IN_USE.
pub fn is_in_use(&self) -> bool {
self.code == curl_sys::CURLSHE_IN_USE
}
/// Returns whether this error corresponds to CURLSHE_INVALID.
pub fn is_invalid(&self) -> bool {
self.code == curl_sys::CURLSHE_INVALID
}
/// Returns whether this error corresponds to CURLSHE_NOMEM.
pub fn is_nomem(&self) -> bool {
self.code == curl_sys::CURLSHE_NOMEM
}
// /// Returns whether this error corresponds to CURLSHE_NOT_BUILT_IN.
// pub fn is_not_built_in(&self) -> bool {
// self.code == curl_sys::CURLSHE_NOT_BUILT_IN
// }
/// Returns the value of the underlying error corresponding to libcurl.
pub fn code(&self) -> curl_sys::CURLSHcode {
self.code
}
}
impl fmt::Display for ShareError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
error::Error::description(self).fmt(f)
}
}
impl fmt::Debug for ShareError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ShareError {{ description: {:?}, code: {} }}",
error::Error::description(self),
self.code)
}
}
impl error::Error for ShareError {
fn description(&self) -> &str {
unsafe {
let s = curl_sys::curl_share_strerror(self.code);
assert!(!s.is_null());
str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
}
}
}
/// An error from "multi" operations.
///
/// THis structure wraps a `CURLMcode`.
#[derive(Clone, PartialEq)]
pub struct MultiError {
code: curl_sys::CURLMcode,
}
impl MultiError {
/// Creates a new error from the underlying code returned by libcurl.
pub fn new(code: curl_sys::CURLMcode) -> MultiError {
MultiError { code: code }
}
/// Returns whether this error corresponds to CURLM_BAD_HANDLE.
pub fn is_bad_handle(&self) -> bool {
self.code == curl_sys::CURLM_BAD_HANDLE
}
/// Returns whether this error corresponds to CURLM_BAD_EASY_HANDLE.
pub fn is_bad_easy_handle(&self) -> bool {
self.code == curl_sys::CURLM_BAD_EASY_HANDLE
}
/// Returns whether this error corresponds to CURLM_OUT_OF_MEMORY.
pub fn is_out_of_memory(&self) -> bool {
self.code == curl_sys::CURLM_OUT_OF_MEMORY
}
/// Returns whether this error corresponds to CURLM_INTERNAL_ERROR.
pub fn is_internal_error(&self) -> bool {
self.code == curl_sys::CURLM_INTERNAL_ERROR
}
/// Returns whether this error corresponds to CURLM_BAD_SOCKET.
pub fn is_bad_socket(&self) -> bool {
self.code == curl_sys::CURLM_BAD_SOCKET
}
/// Returns whether this error corresponds to CURLM_UNKNOWN_OPTION.
pub fn is_unknown_option(&self) -> bool {
self.code == curl_sys::CURLM_UNKNOWN_OPTION
}
/// Returns whether this error corresponds to CURLM_CALL_MULTI_PERFORM.
pub fn is_call_perform(&self) -> bool {
self.code == curl_sys::CURLM_CALL_MULTI_PERFORM
}
// /// Returns whether this error corresponds to CURLM_ADDED_ALREADY.
// pub fn is_added_already(&self) -> bool {
// self.code == curl_sys::CURLM_ADDED_ALREADY
// }
/// Returns the value of the underlying error corresponding to libcurl.
pub fn code(&self) -> curl_sys::CURLMcode {
self.code
}
}
impl fmt::Display for MultiError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
error::Error::description(self).fmt(f)
}
}
impl fmt::Debug for MultiError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "MultiError {{ description: {:?}, code: {} }}",
error::Error::description(self),
self.code)
}
}
impl error::Error for MultiError {
fn description(&self) -> &str {
unsafe {
let s = curl_sys::curl_multi_strerror(self.code);
assert!(!s.is_null());
str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap()
}
}
}
/// An error from "form add" operations.
///
/// THis structure wraps a `CURLFORMcode`.
#[derive(Clone, PartialEq)]
pub struct FormError {
code: curl_sys::CURLFORMcode,
}
impl FormError {
/// Creates a new error from the underlying code returned by libcurl.
pub fn new(code: curl_sys::CURLFORMcode) -> FormError {
FormError { code: code }
}
/// Returns whether this error corresponds to CURL_FORMADD_MEMORY.
pub fn is_memory(&self) -> bool {
self.code == curl_sys::CURL_FORMADD_MEMORY
}
/// Returns whether this error corresponds to CURL_FORMADD_OPTION_TWICE.
pub fn is_option_twice(&self) -> bool {
self.code == curl_sys::CURL_FORMADD_OPTION_TWICE
}
/// Returns whether this error corresponds to CURL_FORMADD_NULL.
pub fn is_null(&self) -> bool {
self.code == curl_sys::CURL_FORMADD_NULL
}
/// Returns whether this error corresponds to CURL_FORMADD_UNKNOWN_OPTION.
pub fn is_unknown_option(&self) -> bool {
self.code == curl_sys::CURL_FORMADD_UNKNOWN_OPTION
}
/// Returns whether this error corresponds to CURL_FORMADD_INCOMPLETE.
pub fn is_incomplete(&self) -> bool {
self.code == curl_sys::CURL_FORMADD_INCOMPLETE
}
/// Returns whether this error corresponds to CURL_FORMADD_ILLEGAL_ARRAY.
pub fn is_illegal_array(&self) -> bool {
self.code == curl_sys::CURL_FORMADD_ILLEGAL_ARRAY
}
/// Returns whether this error corresponds to CURL_FORMADD_DISABLED.
pub fn is_disabled(&self) -> bool {
self.code == curl_sys::CURL_FORMADD_DISABLED
}
/// Returns the value of the underlying error corresponding to libcurl.
pub fn code(&self) -> curl_sys::CURLFORMcode {
self.code
}
}
impl fmt::Display for FormError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
error::Error::description(self).fmt(f)
}
}
impl fmt::Debug for FormError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FormError {{ description: {:?}, code: {} }}",
error::Error::description(self),
self.code)
}
}
impl error::Error for FormError {
fn description(&self) -> &str {
match self.code {
curl_sys::CURL_FORMADD_MEMORY => "allocation failure",
curl_sys::CURL_FORMADD_OPTION_TWICE => "one option passed twice",
curl_sys::CURL_FORMADD_NULL => "null pointer given for string",
curl_sys::CURL_FORMADD_UNKNOWN_OPTION => "unknown option",
curl_sys::CURL_FORMADD_INCOMPLETE => "form information not complete",
curl_sys::CURL_FORMADD_ILLEGAL_ARRAY => "illegal array in option",
curl_sys::CURL_FORMADD_DISABLED => {
"libcurl does not have support for this option compiled in"
}
_ => "unknown form error",
}
}
}
impl From<ffi::NulError> for Error {
fn from(_: ffi::NulError) -> Error {
Error { code: curl_sys::CURLE_CONV_FAILED, extra: None }
}
}
impl From<Error> for io::Error {
fn from(e: Error) -> io::Error {
io::Error::new(io::ErrorKind::Other, e)
}
}
impl From<ShareError> for io::Error {
fn from(e: ShareError) -> io::Error {
io::Error::new(io::ErrorKind::Other, e)
}
}
impl From<MultiError> for io::Error {
fn from(e: MultiError) -> io::Error {
io::Error::new(io::ErrorKind::Other, e)
}
}
impl From<FormError> for io::Error {
fn from(e: FormError) -> io::Error {
io::Error::new(io::ErrorKind::Other, e)
}
}