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
11unsafe 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}