diff --git a/wfassoc_dylib/src/lib.rs b/wfassoc_dylib/src/lib.rs index e4f99f9..0804cdc 100644 --- a/wfassoc_dylib/src/lib.rs +++ b/wfassoc_dylib/src/lib.rs @@ -1,3 +1,79 @@ +use std::cell::RefCell; +use std::ffi::{CString, c_char}; +use thiserror::Error as TeError; + +// region: Error + +/// Error occurs in this crate. +#[derive(Debug, TeError)] +enum Error { + /// Error occurs in wfassoc core. + #[error("{0}")] + Core(#[from] wfassoc::Error), + + #[error("error occurs when parsing into C/C++ string")] + CastIntoCStr(#[from] std::ffi::NulError), + #[error("error occurs when parsing from C/C++ string")] + CastFromCStr(#[from] std::ffi::IntoStringError), +} + +/// Result type used in this crate. +type Result = std::result::Result; + +// endregion + +// region: Last Error + +struct LastError { + msg: CString, +} + +impl LastError { + fn new() -> Self { + Self { + msg: CString::new("").expect("empty string must be valid for CString"), + } + } + + pub fn set_msg(&mut self, msg: &str) { + self.msg = CString::new(msg).expect("unexpected blank in error message output"); + } + + pub fn get_msg(&self) -> *const c_char { + self.msg.as_ptr() + } + + pub fn clear_msg(&mut self) { + self.msg = CString::new("").expect("empty string must be valid for CString"); + } +} + +thread_local! { + static LAST_ERROR: RefCell = RefCell::new(LastError::new()); +} + +fn set_last_error(msg: &str) { + LAST_ERROR.with(|e| { + e.borrow_mut().set_msg(msg); + }); +} + +fn get_last_error() -> *const c_char { + LAST_ERROR.with(|e| e.borrow().get_msg()) +} + +fn clear_last_error() { + LAST_ERROR.with(|e| { + e.borrow_mut().clear_msg(); + }); +} + +// endregion + +// region: Macros + + +// endregion #[unsafe(no_mangle)] pub extern "C" fn WFAdd(left: u32, right: u32) -> u32 {