windows_helpers/win32_app/
error.rs1use super::msg_loop;
2use crate::windows;
3use std::cell::RefCell;
4use windows::Win32::UI::WindowsAndMessaging::PostQuitMessage;
5
6thread_local! {
7 static APP_ERROR: RefCell<Option<Box<dyn std::error::Error + Send + Sync>>> = RefCell::new(None);
8}
9
10pub fn set_app_error_if_absent<E>(error: E)
11where
12 E: Into<Box<dyn std::error::Error + Send + Sync>>,
13{
14 APP_ERROR.with_borrow_mut(|app_error| {
17 if app_error.is_none() {
18 *app_error = Some(error.into());
19 }
20 });
21}
22
23pub fn clear_app_error() {
24 APP_ERROR.with_borrow_mut(|app_error| {
25 *app_error = None;
26 });
27}
28
29pub fn take_app_error() -> Option<Box<dyn std::error::Error + Send + Sync>> {
30 APP_ERROR.with_borrow_mut(|app_error| app_error.take())
33}
34
35pub fn just_try<F, T, E>(action: F) -> Result<T, E>
45where
46 F: FnOnce() -> Result<T, E>,
47{
48 action()
51}
52
53pub fn try_or_set_app_error<F, T, E>(action: F) -> Option<T>
54where
55 F: FnOnce() -> Result<T, E>,
56 E: Into<Box<dyn std::error::Error + Send + Sync>>,
57{
58 match action() {
61 Ok(t) => Some(t),
62 Err(error) => {
63 set_app_error_if_absent(error);
64 None
65 }
66 }
67}
68
69pub fn try_or_post_quit<F, T, E>(action: F) -> Option<T>
70where
71 F: FnOnce() -> Result<T, E>,
72 E: Into<Box<dyn std::error::Error + Send + Sync>>,
73{
74 let option = try_or_set_app_error(action);
79 if option.is_none() {
80 unsafe { PostQuitMessage(1) };
81 }
82 option
83}
84
85pub fn try_or_quit_now<F, T, E>(action: F) -> Option<T>
86where
87 F: FnOnce() -> Result<T, E>,
88 E: Into<Box<dyn std::error::Error + Send + Sync>>,
89{
90 let option = try_or_set_app_error(action);
93 if option.is_none() {
94 msg_loop::quit_now(1);
95 }
96 option
97}
98
99pub fn try_or_panic<F, T, E>(action: F) -> T
100where
101 F: FnOnce() -> Result<T, E>,
102 E: Into<Box<dyn std::error::Error + Send + Sync>>,
103{
104 action().unwrap_or_else(|e| {
107 let error: Box<dyn std::error::Error> = e.into();
108 panic!("{:?}", error);
109 })
110}
111
112pub fn try_then_favor_app_error<F, T, E>(
113 action: F,
114) -> Result<T, Box<dyn std::error::Error + Send + Sync>>
115where
116 F: FnOnce() -> Result<T, E>,
117 E: Into<Box<dyn std::error::Error + Send + Sync>>,
118{
119 let result = action();
129 if let Some(error) = take_app_error() {
130 Err(error)
131 } else {
132 result.map_err(|e| e.into())
133 }
134}