use hojicha_core::event::Event;
use std::any::Any;
use std::panic::AssertUnwindSafe;
use std::sync::mpsc::SyncSender;
pub fn format_panic_message(panic: Box<dyn Any + Send>, context: &str) -> String {
let panic_msg = if let Some(s) = panic.downcast_ref::<String>() {
s.clone()
} else if let Some(s) = panic.downcast_ref::<&str>() {
s.to_string()
} else {
"Unknown panic".to_string()
};
format!("{}: {}", context, panic_msg)
}
pub fn execute_with_panic_recovery<M, F>(f: F, tx: &SyncSender<Event<M>>, context: &str)
where
F: FnOnce() -> Option<M> + std::panic::UnwindSafe,
M: Send + 'static,
{
let result = std::panic::catch_unwind(f);
match result {
Ok(Some(msg)) => {
let _ = tx.send(Event::User(msg));
}
Ok(None) => {
}
Err(panic) => {
let panic_msg = format_panic_message(panic, context);
eprintln!("{}", panic_msg);
}
}
}
pub fn execute_fallible_with_panic_recovery<M, F>(f: F, tx: &SyncSender<Event<M>>, context: &str)
where
F: FnOnce() -> Result<Option<M>, Box<dyn std::error::Error + Send + Sync>>
+ std::panic::UnwindSafe,
M: Send + 'static,
{
let result = std::panic::catch_unwind(AssertUnwindSafe(f));
match result {
Ok(Ok(Some(msg))) => {
let _ = tx.send(Event::User(msg));
}
Ok(Ok(None)) => {
}
Ok(Err(error)) => {
eprintln!("{}: {}", context, error);
}
Err(panic) => {
let panic_msg = format_panic_message(panic, context);
eprintln!("{}", panic_msg);
}
}
}