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 { left + right }