use super::msg_loop;
use crate::windows;
use std::cell::RefCell;
use windows::Win32::UI::WindowsAndMessaging::PostQuitMessage;
thread_local! {
static APP_ERROR: RefCell<Option<Box<dyn std::error::Error + Send + Sync>>> = RefCell::new(None);
}
pub fn set_app_error_if_absent<E>(error: E)
where
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
APP_ERROR.with_borrow_mut(|app_error| {
if app_error.is_none() {
*app_error = Some(error.into());
}
});
}
pub fn clear_app_error() {
APP_ERROR.with_borrow_mut(|app_error| {
*app_error = None;
});
}
pub fn take_app_error() -> Option<Box<dyn std::error::Error + Send + Sync>> {
APP_ERROR.with_borrow_mut(|app_error| app_error.take())
}
pub fn just_try<F, T, E>(action: F) -> Result<T, E>
where
F: FnOnce() -> Result<T, E>,
{
action()
}
pub fn try_or_set_app_error<F, T, E>(action: F) -> Option<T>
where
F: FnOnce() -> Result<T, E>,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
match action() {
Ok(t) => Some(t),
Err(error) => {
set_app_error_if_absent(error);
None
}
}
}
pub fn try_or_post_quit<F, T, E>(action: F) -> Option<T>
where
F: FnOnce() -> Result<T, E>,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
let option = try_or_set_app_error(action);
if option.is_none() {
unsafe { PostQuitMessage(1) };
}
option
}
pub fn try_or_quit_now<F, T, E>(action: F) -> Option<T>
where
F: FnOnce() -> Result<T, E>,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
let option = try_or_set_app_error(action);
if option.is_none() {
msg_loop::quit_now(1);
}
option
}
pub fn try_or_panic<F, T, E>(action: F) -> T
where
F: FnOnce() -> Result<T, E>,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
action().unwrap_or_else(|e| {
let error: Box<dyn std::error::Error> = e.into();
panic!("{:?}", error);
})
}
pub fn try_then_favor_app_error<F, T, E>(
action: F,
) -> Result<T, Box<dyn std::error::Error + Send + Sync>>
where
F: FnOnce() -> Result<T, E>,
E: Into<Box<dyn std::error::Error + Send + Sync>>,
{
let result = action();
if let Some(error) = take_app_error() {
Err(error)
} else {
result.map_err(|e| e.into())
}
}