use thiserror::Error;
pub type Result<T> = std::result::Result<T, CurlError>;
#[derive(Error, Debug)]
pub enum CurlError {
#[error("Failed to initialize curl")]
InitError,
#[error("Curl error {code}: {message}")]
CurlCode {
code: curl_sys::CURLcode,
message: String,
},
#[error("Curl multi error {code}: {message}")]
MultiError {
code: curl_sys::CURLMcode,
message: String,
},
#[error("Invalid URL: {0}")]
InvalidUrl(String),
#[error("Invalid option value: {0}")]
InvalidOption(String),
#[error("WebSocket error: {0}")]
WebSocketError(String),
#[error("UTF-8 conversion error: {0}")]
Utf8Error(#[from] std::str::Utf8Error),
#[error("I/O error: {0}")]
IoError(#[from] std::io::Error),
#[error("Cannot perform operation on closed handle")]
HandleClosed,
#[error("{0}")]
Other(String),
}
impl CurlError {
pub fn from_curl_code(code: curl_sys::CURLcode) -> Self {
let message = unsafe {
let msg_ptr = curl_sys::curl_easy_strerror(code);
std::ffi::CStr::from_ptr(msg_ptr)
.to_string_lossy()
.into_owned()
};
CurlError::CurlCode { code, message }
}
pub fn code(&self) -> Option<u32> {
match self {
CurlError::CurlCode { code, .. } => Some(*code),
CurlError::MultiError { code, .. } => Some(*code as u32),
_ => None,
}
}
}
pub(crate) fn check_code(code: curl_sys::CURLcode) -> Result<()> {
if code == curl_sys::CURLE_OK {
Ok(())
} else {
Err(CurlError::from_curl_code(code))
}
}