hojicha_runtime/
panic_utils.rs1use hojicha_core::event::Event;
7use std::any::Any;
8use std::panic::AssertUnwindSafe;
9use std::sync::mpsc::SyncSender;
10
11pub fn format_panic_message(panic: Box<dyn Any + Send>, context: &str) -> String {
13 let panic_msg = if let Some(s) = panic.downcast_ref::<String>() {
14 s.clone()
15 } else if let Some(s) = panic.downcast_ref::<&str>() {
16 s.to_string()
17 } else {
18 "Unknown panic".to_string()
19 };
20
21 format!("{}: {}", context, panic_msg)
22}
23
24pub fn execute_with_panic_recovery<M, F>(f: F, tx: &SyncSender<Event<M>>, context: &str)
26where
27 F: FnOnce() -> Option<M> + std::panic::UnwindSafe,
28 M: Send + 'static,
29{
30 let result = std::panic::catch_unwind(f);
31
32 match result {
33 Ok(Some(msg)) => {
34 let _ = tx.send(Event::User(msg));
35 }
36 Ok(None) => {
37 }
39 Err(panic) => {
40 let panic_msg = format_panic_message(panic, context);
41 eprintln!("{}", panic_msg);
42 }
43 }
44}
45
46pub fn execute_fallible_with_panic_recovery<M, F>(f: F, tx: &SyncSender<Event<M>>, context: &str)
48where
49 F: FnOnce() -> Result<Option<M>, Box<dyn std::error::Error + Send + Sync>>
50 + std::panic::UnwindSafe,
51 M: Send + 'static,
52{
53 let result = std::panic::catch_unwind(AssertUnwindSafe(f));
54
55 match result {
56 Ok(Ok(Some(msg))) => {
57 let _ = tx.send(Event::User(msg));
58 }
59 Ok(Ok(None)) => {
60 }
62 Ok(Err(error)) => {
63 eprintln!("{}: {}", context, error);
64 }
65 Err(panic) => {
66 let panic_msg = format_panic_message(panic, context);
67 eprintln!("{}", panic_msg);
68 }
69 }
70}