1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use thiserror::Error; |
4 | |
5 | use crate::{prelude::ElementExt, ErrorMessage, FlowReturn}; |
6 | |
7 | #[doc (hidden)] |
8 | #[inline (never)] |
9 | pub fn post_panic_error_message( |
10 | element: &crate::Element, |
11 | src: &crate::Object, |
12 | panic: Option<Box<dyn std::any::Any + Send + 'static>>, |
13 | ) { |
14 | let cause: Option<&str> = panic.as_ref().and_then(|err: &Box| { |
15 | errOption<&str>.downcast_ref::<&str>() |
16 | .copied() |
17 | .or_else(|| err.downcast_ref::<String>().map(|s: &String| s.as_str())) |
18 | }); |
19 | |
20 | let msg: Message = if let Some(cause: &str) = cause { |
21 | crateErrorBuilder<'_>::message::Error::builder(error:crate::LibraryError::Failed, &format!("Panicked: {cause}" )) |
22 | .src(src) |
23 | .build() |
24 | } else { |
25 | crateErrorBuilder<'_>::message::Error::builder(error:crate::LibraryError::Failed, message:"Panicked" ) |
26 | .src(src) |
27 | .build() |
28 | }; |
29 | |
30 | let _ = element.post_message(msg); |
31 | } |
32 | |
33 | #[macro_export ] |
34 | macro_rules! panic_to_error( |
35 | ($imp:expr, $ret:expr, $code:block) => {{ |
36 | #[allow(clippy::unused_unit)] |
37 | #[cfg(panic = "abort" )] |
38 | { |
39 | if true { |
40 | #[allow(unused_mut)] |
41 | let mut closure = || { $code }; |
42 | closure() |
43 | } else { |
44 | let _imp = $imp; |
45 | $ret |
46 | } |
47 | } |
48 | #[cfg(not(panic = "abort" ))] |
49 | { |
50 | let panicked = $imp.panicked(); |
51 | let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp); |
52 | let element = unsafe { $crate::glib::prelude::Cast::unsafe_cast_ref::<$crate::Element>(element.as_ref()) }; |
53 | if panicked.load(std::sync::atomic::Ordering::Relaxed) { |
54 | $crate::subclass::post_panic_error_message( |
55 | element, |
56 | $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(element), |
57 | None, |
58 | ); |
59 | $ret |
60 | } else { |
61 | let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code)); |
62 | |
63 | match result { |
64 | Ok(result) => result, |
65 | Err(err) => { |
66 | panicked.store(true, std::sync::atomic::Ordering::Relaxed); |
67 | $crate::subclass::post_panic_error_message( |
68 | element, |
69 | $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(element), |
70 | Some(err), |
71 | ); |
72 | $ret |
73 | } |
74 | } |
75 | } |
76 | } |
77 | }}; |
78 | ); |
79 | |
80 | #[derive (Clone, Debug, PartialEq, Eq, Error)] |
81 | pub enum FlowError { |
82 | #[error("Flushing" )] |
83 | Flushing, |
84 | #[error("Eos" )] |
85 | Eos, |
86 | #[error("Not Negotiated" )] |
87 | NotNegotiated(ErrorMessage), |
88 | #[error("Error" )] |
89 | Error(ErrorMessage), |
90 | } |
91 | |
92 | impl From<FlowError> for FlowReturn { |
93 | fn from(err: FlowError) -> Self { |
94 | FlowReturn::from(&err) |
95 | } |
96 | } |
97 | |
98 | impl From<&FlowError> for FlowReturn { |
99 | fn from(err: &FlowError) -> FlowReturn { |
100 | match *err { |
101 | FlowError::Flushing => FlowReturn::Flushing, |
102 | FlowError::Eos => FlowReturn::Eos, |
103 | FlowError::NotNegotiated(..) => FlowReturn::NotNegotiated, |
104 | FlowError::Error(..) => FlowReturn::Error, |
105 | } |
106 | } |
107 | } |
108 | |