Skip to main content

wingy_core/
error.rs

1use std::error::Error;
2use std::fmt::{self, Display};
3
4use crate::data_transfer::DataTransferId;
5
6/// A general error that may occur while running or creating
7/// the event loop.
8#[derive(Debug)]
9#[non_exhaustive]
10pub enum EventLoopError {
11    /// The event loop can't be re-created.
12    RecreationAttempt,
13    /// Application has exit with an error status.
14    ExitFailure(i32),
15    /// Got unspecified OS-specific error during the request.
16    Os(OsError),
17    /// Creating the event loop with the requested configuration is not supported.
18    NotSupported(NotSupportedError),
19}
20
21impl fmt::Display for EventLoopError {
22    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
23        match self {
24            Self::RecreationAttempt => {
25                write!(
26                    f,
27                    "EventLoop can't be recreated, only a single instance of it is supported (for \
28                     cross-platform compatibility)"
29                )
30            },
31            Self::Os(err) => err.fmt(f),
32            Self::ExitFailure(status) => write!(f, "Exit Failure: {status}"),
33            Self::NotSupported(err) => err.fmt(f),
34        }
35    }
36}
37
38impl Error for EventLoopError {
39    fn source(&self) -> Option<&(dyn Error + 'static)> {
40        if let Self::Os(err) = self { err.source() } else { None }
41    }
42}
43
44impl From<OsError> for EventLoopError {
45    fn from(value: OsError) -> Self {
46        Self::Os(value)
47    }
48}
49
50impl From<NotSupportedError> for EventLoopError {
51    fn from(value: NotSupportedError) -> Self {
52        Self::NotSupported(value)
53    }
54}
55
56/// Window creation failure
57#[derive(Debug)]
58#[non_exhaustive]
59pub enum CreateWindowError {
60    /// [`WindowType::Popup`](crate::window::WindowType::Popup) is not supported.
61    PopupNotSupported,
62    /// Invalid input attribute
63    InvalidAttribute(InvalidInput),
64    /// Got unspecified OS specific error during the request.
65    Os(OsError),
66}
67
68impl Display for CreateWindowError {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        match self {
71            Self::PopupNotSupported => write!(f, "WindowType::Popup is not supported"),
72            Self::InvalidAttribute(InvalidInput { reason }) => {
73                write!(f, "Invalid WindowAttributes: {reason}")
74            },
75            Self::Os(err) => err.fmt(f),
76        }
77    }
78}
79impl Error for CreateWindowError {
80    fn source(&self) -> Option<&(dyn Error + 'static)> {
81        if let Self::Os(err) = self { err.source() } else { None }
82    }
83}
84
85impl From<InvalidInput> for CreateWindowError {
86    fn from(value: InvalidInput) -> Self {
87        Self::InvalidAttribute(value)
88    }
89}
90
91impl From<OsError> for CreateWindowError {
92    fn from(value: OsError) -> Self {
93        Self::Os(value)
94    }
95}
96
97/// A data transfer / drag-and-drop error.
98#[derive(Debug)]
99#[non_exhaustive]
100pub enum TransferError {
101    /// The request is not supported.
102    NotSupported(NotSupportedError),
103    /// Unknown [`DataTransferId`]
104    UnknownTransfer(DataTransferId),
105    /// The transfer (request) failed.
106    Failed,
107    /// Got unspecified OS specific error during the request.
108    Os(OsError),
109}
110
111impl Display for TransferError {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
113        match self {
114            Self::NotSupported(err) => err.fmt(f),
115            Self::UnknownTransfer(id) => {
116                write!(f, "Unknown data transfer with ID {}", id.into_raw())
117            },
118            Self::Failed => write!(f, "Transfer request failed"),
119            Self::Os(err) => err.fmt(f),
120        }
121    }
122}
123impl Error for TransferError {
124    fn source(&self) -> Option<&(dyn Error + 'static)> {
125        if let Self::Os(err) = self { err.source() } else { None }
126    }
127}
128impl From<NotSupportedError> for TransferError {
129    fn from(value: NotSupportedError) -> Self {
130        Self::NotSupported(value)
131    }
132}
133
134impl From<OsError> for TransferError {
135    fn from(value: OsError) -> Self {
136        Self::Os(value)
137    }
138}
139
140/// An error from `create_custom_cursor`.
141#[derive(Debug)]
142#[non_exhaustive]
143pub enum CustomCursorError {
144    /// Custom cursors are not supported.
145    NotSupported,
146    /// The [`CustomCursorSource`](crate::cursor::CustomCursorSource) variant is not supported.
147    UnsupportedSource,
148    /// Got unspecified OS specific error during the request.
149    Os(OsError),
150}
151
152impl Display for CustomCursorError {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        match self {
155            Self::NotSupported => write!(f, "create_custom_cursor is not supported"),
156            Self::UnsupportedSource => {
157                write!(f, "the provided CustomCursorSource is not supported")
158            },
159            Self::Os(err) => err.fmt(f),
160        }
161    }
162}
163impl Error for CustomCursorError {
164    fn source(&self) -> Option<&(dyn Error + 'static)> {
165        if let Self::Os(err) = self { err.source() } else { None }
166    }
167}
168
169impl From<OsError> for CustomCursorError {
170    fn from(value: OsError) -> Self {
171        Self::Os(value)
172    }
173}
174
175/// A general error that may occur during a request to the windowing system.
176#[derive(Debug)]
177#[non_exhaustive]
178pub enum RequestError {
179    /// The request is not supported.
180    NotSupported(NotSupportedError),
181    /// Got unspecified OS specific error during the request.
182    Os(OsError),
183}
184
185impl Display for RequestError {
186    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
187        match self {
188            Self::NotSupported(err) => err.fmt(f),
189            Self::Os(err) => err.fmt(f),
190        }
191    }
192}
193impl Error for RequestError {
194    fn source(&self) -> Option<&(dyn Error + 'static)> {
195        if let Self::Os(err) = self { err.source() } else { None }
196    }
197}
198
199impl From<NotSupportedError> for RequestError {
200    fn from(value: NotSupportedError) -> Self {
201        Self::NotSupported(value)
202    }
203}
204
205impl From<OsError> for RequestError {
206    fn from(value: OsError) -> Self {
207        Self::Os(value)
208    }
209}
210
211/// An input attribute or parameter was not valid
212#[derive(Debug)]
213pub struct InvalidInput {
214    /// The reason why a certain operation is not supported.
215    reason: &'static str,
216}
217
218impl InvalidInput {
219    pub const fn new(reason: &'static str) -> Self {
220        Self { reason }
221    }
222}
223
224impl fmt::Display for InvalidInput {
225    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226        write!(f, "Invalid input: {}", self.reason)
227    }
228}
229impl Error for InvalidInput {}
230
231/// The requested operation is not supported.
232#[derive(Debug)]
233pub struct NotSupportedError {
234    /// The reason why a certain operation is not supported.
235    reason: &'static str,
236}
237
238impl NotSupportedError {
239    pub const fn new(reason: &'static str) -> Self {
240        Self { reason }
241    }
242}
243
244impl fmt::Display for NotSupportedError {
245    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246        write!(f, "Operation is not supported: {}", self.reason)
247    }
248}
249impl Error for NotSupportedError {}
250
251/// An internal failure occurred
252#[derive(Debug)]
253pub struct InternalError {
254    source: &'static str,
255}
256
257impl InternalError {
258    pub const fn new(source: &'static str) -> Self {
259        Self { source }
260    }
261}
262
263impl fmt::Display for InternalError {
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        write!(f, "Internal error: {}", self.source)
266    }
267}
268impl Error for InternalError {}
269
270/// Unclassified error from the OS.
271#[derive(Debug)]
272pub struct OsError {
273    line: u32,
274    file: &'static str,
275    error: Box<dyn Error + Send + Sync + 'static>,
276}
277
278impl OsError {
279    pub fn new(
280        line: u32,
281        file: &'static str,
282        error: impl Into<Box<dyn Error + Send + Sync + 'static>>,
283    ) -> Self {
284        Self { line, file, error: error.into() }
285    }
286}
287
288impl Display for OsError {
289    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
290        f.pad(&format!("os error at {}:{}: {}", self.file, self.line, self.error))
291    }
292}
293impl Error for OsError {
294    fn source(&self) -> Option<&(dyn Error + 'static)> {
295        Some(self.error.as_ref())
296    }
297}
298
299#[allow(unused_macros)]
300macro_rules! os_error {
301    ($error:expr) => {{ crate::error::OsError::new(line!(), file!(), $error) }};
302}