Skip to main content

compio_driver/
panic.rs

1use std::{
2    any::Any,
3    error::Error,
4    fmt::{Debug, Display},
5    io,
6    panic::{UnwindSafe, catch_unwind, resume_unwind},
7};
8
9pub(crate) struct Panic(Box<dyn Any + Send>);
10
11// Panic is unconditionally `Sync`
12unsafe impl Sync for Panic {}
13
14impl Display for Panic {
15    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
16        Debug::fmt(self, f)
17    }
18}
19
20impl Debug for Panic {
21    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
22        f.debug_tuple("Panic").finish_non_exhaustive()
23    }
24}
25
26impl Error for Panic {}
27
28impl From<Panic> for io::Error {
29    fn from(value: Panic) -> Self {
30        Self::other(value)
31    }
32}
33
34pub(crate) fn catch_unwind_io<F, R>(f: F) -> io::Result<R>
35where
36    F: FnOnce() -> io::Result<R> + UnwindSafe,
37{
38    catch_unwind(f).map_err(|err| io::Error::from(Panic(err)))?
39}
40
41pub(crate) fn resume_unwind_io<T>(res: io::Result<T>) -> io::Result<T> {
42    let Err(e) = res else { return res };
43    match e.downcast::<Panic>() {
44        Ok(p) => resume_unwind(p.0),
45        Err(e) => Err(e),
46    }
47}