// Take a look at the license at the top of the repository in the LICENSE file. use thiserror::Error; use crate::{prelude::ElementExt, ErrorMessage, FlowReturn}; #[doc(hidden)] #[inline(never)] pub fn post_panic_error_message( element: &crate::Element, src: &crate::Object, panic: Option>, ) { let cause = panic.as_ref().and_then(|err| { err.downcast_ref::<&str>() .copied() .or_else(|| err.downcast_ref::().map(|s| s.as_str())) }); let msg = if let Some(cause) = cause { crate::message::Error::builder(crate::LibraryError::Failed, &format!("Panicked: {cause}")) .src(src) .build() } else { crate::message::Error::builder(crate::LibraryError::Failed, "Panicked") .src(src) .build() }; let _ = element.post_message(msg); } #[macro_export] macro_rules! panic_to_error( ($imp:expr, $ret:expr, $code:block) => {{ #[allow(clippy::unused_unit)] { let panicked = $imp.panicked(); let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp); let element = unsafe { $crate::glib::Cast::unsafe_cast_ref::<$crate::Element>(element.as_ref()) }; if panicked.load(std::sync::atomic::Ordering::Relaxed) { $crate::subclass::post_panic_error_message( element, $crate::glib::Cast::upcast_ref::<$crate::Object>(element), None, ); $ret } else { let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code)); match result { Ok(result) => result, Err(err) => { panicked.store(true, std::sync::atomic::Ordering::Relaxed); $crate::subclass::post_panic_error_message( element, $crate::glib::Cast::upcast_ref::<$crate::Object>(element), Some(err), ); $ret } } } } }}; ); #[derive(Clone, Debug, PartialEq, Eq, Error)] pub enum FlowError { #[error("Flushing")] Flushing, #[error("Eos")] Eos, #[error("Not Negotiated")] NotNegotiated(ErrorMessage), #[error("Error")] Error(ErrorMessage), } impl From for FlowReturn { fn from(err: FlowError) -> Self { FlowReturn::from(&err) } } impl<'a> From<&'a FlowError> for FlowReturn { fn from(err: &FlowError) -> FlowReturn { match *err { FlowError::Flushing => FlowReturn::Flushing, FlowError::Eos => FlowReturn::Eos, FlowError::NotNegotiated(..) => FlowReturn::NotNegotiated, FlowError::Error(..) => FlowReturn::Error, } } }