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>(
26 f: F,
27 tx: &SyncSender<Event<M>>,
28 context: &str,
29) where
30 F: FnOnce() -> Option<M> + std::panic::UnwindSafe,
31 M: Send + 'static,
32{
33 let result = std::panic::catch_unwind(f);
34
35 match result {
36 Ok(Some(msg)) => {
37 let _ = tx.send(Event::User(msg));
38 }
39 Ok(None) => {
40 }
42 Err(panic) => {
43 let panic_msg = format_panic_message(panic, context);
44 eprintln!("{}", panic_msg);
45 }
46 }
47}
48
49pub fn execute_fallible_with_panic_recovery<M, F>(
51 f: F,
52 tx: &SyncSender<Event<M>>,
53 context: &str,
54) where
55 F: FnOnce() -> Result<Option<M>, Box<dyn std::error::Error + Send + Sync>> + std::panic::UnwindSafe,
56 M: Send + 'static,
57{
58 let result = std::panic::catch_unwind(AssertUnwindSafe(f));
59
60 match result {
61 Ok(Ok(Some(msg))) => {
62 let _ = tx.send(Event::User(msg));
63 }
64 Ok(Ok(None)) => {
65 }
67 Ok(Err(error)) => {
68 eprintln!("{}: {}", context, error);
69 }
70 Err(panic) => {
71 let panic_msg = format_panic_message(panic, context);
72 eprintln!("{}", panic_msg);
73 }
74 }
75}