use std::panic::UnwindSafe;
use ffi_support::{ConcurrentHandleMap, ExternError, IntoFfi};
pub fn handle_result<R, F>(callback: F) -> R::Value
where
F: UnwindSafe + FnOnce() -> Result<R, glean_core::Error>,
R: IntoFfi,
{
let mut error = ffi_support::ExternError::success();
let res = ffi_support::abort_on_panic::call_with_result(&mut error, callback);
log_if_error(error);
res
}
pub fn log_if_error(error: ExternError) {
if !error.get_code().is_success() {
ffi_support::abort_on_panic::call_with_output(|| {
log::warn!(
"Glean failed ({:?}): {}",
error.get_code(),
error.get_message().as_str()
);
unsafe {
error.manually_release();
}
})
}
}
pub trait HandleMapExtension {
type Output;
fn insert_with_log<F>(&self, constructor: F) -> u64
where
F: UnwindSafe + FnOnce() -> Result<Self::Output, glean_core::Error>;
fn call_infallible<R, F>(&self, h: u64, callback: F) -> R::Value
where
F: UnwindSafe + FnOnce(&Self::Output) -> R,
R: IntoFfi;
fn call_infallible_mut<R, F>(&self, h: u64, callback: F) -> R::Value
where
F: UnwindSafe + FnOnce(&mut Self::Output) -> R,
R: IntoFfi;
fn call_with_log<R, F>(&self, h: u64, callback: F) -> R::Value
where
F: UnwindSafe + FnOnce(&Self::Output) -> Result<R, glean_core::Error>,
R: IntoFfi;
}
impl<T> HandleMapExtension for ConcurrentHandleMap<T> {
type Output = T;
fn insert_with_log<F>(&self, constructor: F) -> u64
where
F: UnwindSafe + FnOnce() -> Result<Self::Output, glean_core::Error>,
{
let mut error = ExternError::success();
let res = self.insert_with_result(&mut error, constructor);
log_if_error(error);
res
}
fn call_infallible<R, F>(&self, h: u64, callback: F) -> R::Value
where
F: UnwindSafe + FnOnce(&Self::Output) -> R,
R: IntoFfi,
{
let mut error = ExternError::success();
let res = self.call_with_output(&mut error, h, callback);
debug_assert!(error.get_code().is_success());
res
}
fn call_infallible_mut<R, F>(&self, h: u64, callback: F) -> R::Value
where
F: UnwindSafe + FnOnce(&mut Self::Output) -> R,
R: IntoFfi,
{
let mut error = ExternError::success();
let res = self.call_with_output_mut(&mut error, h, callback);
debug_assert!(error.get_code().is_success());
res
}
fn call_with_log<R, F>(&self, h: u64, callback: F) -> R::Value
where
F: UnwindSafe + FnOnce(&Self::Output) -> Result<R, glean_core::Error>,
R: IntoFfi,
{
let mut error = ExternError::success();
let res = self.call_with_result(&mut error, h, callback);
log_if_error(error);
res
}
}