1use {
4 smol_str::SmolStr,
5 std::fmt::{
6 self,
7 Display,
8 },
9};
10
11#[derive(thiserror::Error, Debug)]
13#[non_exhaustive]
14pub enum RequestError {
15 #[error("The request is not supported. `{0}`")]
17 NotSupported(SmolStr),
18 #[error("The request was ignored by the OS")]
19 Ignored,
20 #[error("OS specific error. `{0}`")]
22 Os(#[from] OsError),
23}
24
25impl RequestError {
26 pub fn not_supported(message: impl Into<SmolStr>) -> Self {
27 Self::NotSupported(message.into())
28 }
29}
30
31#[derive(thiserror::Error, Debug)]
33pub struct OsError {
34 line: u32,
35 file: &'static str,
36 error: Box<dyn std::error::Error + Send + Sync + 'static>,
37}
38
39impl OsError {
40 pub fn new(
41 line: u32,
42 file: &'static str,
43 error: impl Into<Box<dyn std::error::Error + Send + Sync + 'static>>,
44 ) -> Self {
45 Self { line, file, error: error.into() }
46 }
47}
48
49impl Display for OsError {
50 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51 f.pad(&format!("os error at {}:{}: {}", self.file, self.line, self.error))
52 }
53}
54
55pub trait MapToOSError<T, E> {
56 fn map_to_os_err(self) -> Result<T, OsError>
57 where
58 Self: Sized;
59
60 fn request_error(self) -> Result<T, RequestError>
61 where
62 Self: Sized;
63}
64
65impl<T, E> MapToOSError<T, E> for Result<T, E>
66where
67 E: std::error::Error + Send + Sync + 'static,
68{
69 fn map_to_os_err(self) -> Result<T, OsError>
70 where
71 Self: Sized,
72 {
73 match self {
74 Ok(t) => Ok(t),
75 Err(e) => Err(crate::os_error!(e)),
76 }
77 }
78
79 fn request_error(self) -> Result<T, RequestError>
80 where
81 Self: Sized,
82 {
83 Ok(self.map_to_os_err()?)
84 }
85}
86
87#[allow(unused_macros)]
88#[macro_export]
89macro_rules! os_error {
90 ($error:expr) => {{ $crate::error::OsError::new(line!(), file!(), $error) }};
91}
92
93#[allow(unused_macros)]
94#[macro_export]
95macro_rules! os_error_fmt {
96 ($error:expr) => {{ $crate::os_error!(format!($error)) }};
97}