use std::{
ffi::CStr,
fmt::{self, Debug, Display},
os::raw::c_char,
};
#[derive(Clone, PartialEq)]
pub struct Error {
pub(crate) code: Option<i32>,
pub(crate) message: String,
}
impl Error {
pub fn code(&self) -> Option<i32> {
self.code
}
pub(crate) fn custom(message: String) -> Self {
Error {
code: None,
message,
}
}
pub(crate) fn from_code(code: i32) -> Self {
let builtin_message: Result<Option<String>, Error> =
crate::env::with_raw_stdenv(|stdenv| unsafe {
let code_long = std::os::raw::c_long::try_from(code).unwrap();
let message_cptr: *const c_char =
crate::sys::WSErrorString(stdenv, code_long);
if message_cptr.is_null() {
return None;
}
let message_cstr = CStr::from_ptr(message_cptr);
Some(message_cstr.to_str().ok()?.to_owned())
});
let message = match builtin_message {
Ok(Some(message)) => message,
Ok(None) | Err(_) => format!("WSTP error code {} occurred.", code),
};
Error {
code: Some(code),
message,
}
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let Error { code, message } = self;
if let Some(code) = code {
write!(f, "WSTP error (code {}): {}", code, message)
} else {
write!(f, "WSTP error: {}", message)
}
}
}
impl Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self)
}
}
impl std::error::Error for Error {}