mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-05-28 13:18:29 +00:00
b468280353
None of that can ever be called in that case but the compiler can't know that in more complicated cases like these. Handling it explicitly allows no handling code to be generated at all here, like would already happen everywhere else. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1441>
108 lines
3.2 KiB
Rust
108 lines
3.2 KiB
Rust
// 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<Box<dyn std::any::Any + Send + 'static>>,
|
|
) {
|
|
let cause = panic.as_ref().and_then(|err| {
|
|
err.downcast_ref::<&str>()
|
|
.copied()
|
|
.or_else(|| err.downcast_ref::<String>().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)]
|
|
#[cfg(panic = "abort")]
|
|
{
|
|
if true {
|
|
#[allow(unused_mut)]
|
|
let mut closure = || { $code };
|
|
closure()
|
|
} else {
|
|
let _imp = $imp;
|
|
$ret
|
|
}
|
|
}
|
|
#[cfg(not(panic = "abort"))]
|
|
{
|
|
let panicked = $imp.panicked();
|
|
let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp);
|
|
let element = unsafe { $crate::glib::prelude::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::prelude::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::prelude::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<FlowError> 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,
|
|
}
|
|
}
|
|
}
|