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 | { |
38 | let panicked = $imp.panicked(); |
39 | let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp); |
40 | let element = unsafe { $crate::glib::Cast::unsafe_cast_ref::<$crate::Element>(element.as_ref()) }; |
41 | if panicked.load(std::sync::atomic::Ordering::Relaxed) { |
42 | $crate::subclass::post_panic_error_message( |
43 | element, |
44 | $crate::glib::Cast::upcast_ref::<$crate::Object>(element), |
45 | None, |
46 | ); |
47 | $ret |
48 | } else { |
49 | let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code)); |
50 | |
51 | match result { |
52 | Ok(result) => result, |
53 | Err(err) => { |
54 | panicked.store(true, std::sync::atomic::Ordering::Relaxed); |
55 | $crate::subclass::post_panic_error_message( |
56 | element, |
57 | $crate::glib::Cast::upcast_ref::<$crate::Object>(element), |
58 | Some(err), |
59 | ); |
60 | $ret |
61 | } |
62 | } |
63 | } |
64 | } |
65 | }}; |
66 | ); |
67 | |
68 | #[derive (Clone, Debug, PartialEq, Eq, Error)] |
69 | pub enum FlowError { |
70 | #[error("Flushing" )] |
71 | Flushing, |
72 | #[error("Eos" )] |
73 | Eos, |
74 | #[error("Not Negotiated" )] |
75 | NotNegotiated(ErrorMessage), |
76 | #[error("Error" )] |
77 | Error(ErrorMessage), |
78 | } |
79 | |
80 | impl From<FlowError> for FlowReturn { |
81 | fn from(err: FlowError) -> Self { |
82 | FlowReturn::from(&err) |
83 | } |
84 | } |
85 | |
86 | impl<'a> From<&'a FlowError> for FlowReturn { |
87 | fn from(err: &FlowError) -> FlowReturn { |
88 | match *err { |
89 | FlowError::Flushing => FlowReturn::Flushing, |
90 | FlowError::Eos => FlowReturn::Eos, |
91 | FlowError::NotNegotiated(..) => FlowReturn::NotNegotiated, |
92 | FlowError::Error(..) => FlowReturn::Error, |
93 | } |
94 | } |
95 | } |
96 | |