summaryrefslogtreecommitdiff
path: root/libs/all_in_one/src/errors.rs
diff options
context:
space:
mode:
Diffstat (limited to 'libs/all_in_one/src/errors.rs')
-rw-r--r--libs/all_in_one/src/errors.rs53
1 files changed, 53 insertions, 0 deletions
diff --git a/libs/all_in_one/src/errors.rs b/libs/all_in_one/src/errors.rs
new file mode 100644
index 0000000..d2c7444
--- /dev/null
+++ b/libs/all_in_one/src/errors.rs
@@ -0,0 +1,53 @@
+use std::cell::RefCell;
+
+use anyhow::Result;
+use tracing::error;
+
+thread_local! {
+ pub static ERROR_HANDLER: std::cell::RefCell<Option<unsafe extern "C" fn(libc::c_int, *mut libc::c_char)>> = RefCell::new(None);
+}
+
+/// Update the most recent error, clearing whatever may have been there before.
+#[must_use] pub fn stacktrace(err: &anyhow::Error) -> String {
+ format!("{err}")
+}
+
+pub fn wrap_result<T, F>(func: F) -> Option<T>
+where
+ F: Fn() -> Result<T>,
+{
+ let result = func();
+
+ match result {
+ Ok(ok) => Some(ok),
+ Err(error) => {
+ // Call the handler
+ handle_error(&error);
+ None
+ }
+ }
+}
+
+/// # Panics
+/// Panics if the stacktrace size is > than an i32
+pub fn handle_error(error: &anyhow::Error) {
+ ERROR_HANDLER.with(|val| {
+ let mut stacktrace = stacktrace(error);
+
+ error!("Error emitted: {}", stacktrace);
+ if let Some(func) = *val.borrow() {
+ // Call the error handler
+ unsafe {
+ func(
+ (stacktrace.len() + 1).try_into().unwrap(),
+ stacktrace.as_mut_ptr().cast::<libc::c_char>(),
+ );
+ }
+ }
+ });
+}
+
+#[cfg(test)]
+mod tests {
+ // todo
+}