euv_ui/hook/error_boundary/fn.rs
1use super::*;
2
3/// Extracts the panic message from a `catch_unwind` payload.
4///
5/// `catch_unwind` returns a `Box<dyn Any + Send>`. The boxed type
6/// is whatever the panic site threw — most commonly a `String` /
7/// `&str`, but Rust also supports throwing `&'static str` from
8/// `std::panic!`. This helper tries each, in order, and falls
9/// back to `"<unknown panic payload>"` so the boundary always
10/// has a useful message to display.
11///
12/// # Arguments
13///
14/// - `&Box<dyn Any + Send>` - The boxed payload from
15/// [`std::panic::catch_unwind`].
16///
17/// # Returns
18///
19/// - `String` - The recovered panic message.
20pub(crate) fn extract_message(payload: &Box<dyn Any + Send>) -> String {
21 if let Some(s) = payload.downcast_ref::<String>() {
22 return s.clone();
23 }
24 if let Some(s) = payload.downcast_ref::<&'static str>() {
25 return (*s).to_string();
26 }
27 String::from("<unknown panic payload>")
28}
29
30/// Obtains an `ErrorBoundary` registered against the current hook context slot.
31///
32/// Behaves like `HookContext::use_hook`: the same `ErrorBoundary` is
33/// returned on every render at the same hook index, preserving the
34/// `Idle` / `Caught(message)` phase across renders.
35///
36/// Use [`ErrorBoundary::try_with`] to run a closure under the
37/// boundary; panics inside the closure are caught and the phase
38/// transitions to `Caught`. The parent's render code reads
39/// [`ErrorBoundary::phase`] (a `Signal<ErrorBoundaryPhase>`) to decide
40/// whether to render the children or a fallback.
41///
42/// # Returns
43///
44/// - `ErrorBoundary` - The error boundary handle.
45/// Returns the factory result directly when no hook context is
46/// active (e.g. when called outside a render cycle).
47pub fn use_error_boundary() -> ErrorBoundary {
48 HookContext::use_hook(ErrorBoundary::default)
49}