use crate::UnhandledErrorException;
use ferroui_system::ObservableError;
use std::any::Any;
use std::error::Error;
use std::fmt;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::rc::Rc;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PanicException {
pub message: String,
}
impl fmt::Display for PanicException {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl Error for PanicException {}
impl PanicException {
pub fn from_payload(payload: &(dyn Any + Send)) -> ObservableError {
if let Some(exception) = payload.downcast_ref::<UnhandledErrorException>() {
return Rc::new(exception.clone());
}
let message = payload
.downcast_ref::<&str>()
.map(|text| (*text).to_owned())
.or_else(|| payload.downcast_ref::<String>().cloned())
.unwrap_or_else(|| "the code panicked".to_owned());
Rc::new(PanicException { message })
}
pub fn catch<R>(action: impl FnOnce() -> R) -> Result<R, (ObservableError, Box<dyn Any + Send>)> {
catch_unwind(AssertUnwindSafe(action)).map_err(|payload| (Self::from_payload(&*payload), payload))
}
}