1use raw_window_handle::{RawDisplayHandle, RawWindowHandle};
2use std::error::Error;
3use std::fmt;
4use std::num::NonZeroU32;
5
6#[derive(Debug)]
7#[non_exhaustive]
8/// A sum type of all of the errors that can occur during the operation of this crate.
9pub enum SoftBufferError {
10 /// The [`RawDisplayHandle`] passed into [`Context::new`] is not supported by this crate.
11 ///
12 /// [`RawDisplayHandle`]: raw_window_handle::RawDisplayHandle
13 /// [`Context::new`]: crate::Context::new
14 UnsupportedDisplayPlatform {
15 /// The platform name of the display that was passed into [`Context::new`].
16 ///
17 /// This is a human-readable string that describes the platform of the display that was
18 /// passed into [`Context::new`]. The value is not guaranteed to be stable and this
19 /// exists for debugging purposes only.
20 ///
21 /// [`Context::new`]: crate::Context::new
22 human_readable_display_platform_name: &'static str,
23
24 /// The [`RawDisplayHandle`] that was passed into [`Context::new`].
25 ///
26 /// [`RawDisplayHandle`]: raw_window_handle::RawDisplayHandle
27 /// [`Context::new`]: crate::Context::new
28 display_handle: RawDisplayHandle,
29 },
30
31 /// The [`RawWindowHandle`] passed into [`Surface::new`] is not supported by this crate.
32 ///
33 /// [`RawWindowHandle`]: raw_window_handle::RawWindowHandle
34 /// [`Surface::new`]: crate::Surface::new
35 UnsupportedWindowPlatform {
36 /// The platform name of the window that was passed into [`Surface::new`].
37 ///
38 /// This is a human-readable string that describes the platform of the window that was
39 /// passed into [`Surface::new`]. The value is not guaranteed to be stable and this
40 /// exists for debugging purposes only.
41 ///
42 /// [`Surface::new`]: crate::Surface::new
43 human_readable_window_platform_name: &'static str,
44
45 /// The platform name of the display used by the [`Context`].
46 ///
47 /// It is possible for a window to be created on a different type of display than the
48 /// display that was passed into [`Context::new`]. This is a human-readable string that
49 /// describes the platform of the display that was passed into [`Context::new`]. The value
50 /// is not guaranteed to be stable and this exists for debugging purposes only.
51 ///
52 /// [`Context`]: crate::Context
53 /// [`Context::new`]: crate::Context::new
54 human_readable_display_platform_name: &'static str,
55
56 /// The [`RawWindowHandle`] that was passed into [`Surface::new`].
57 ///
58 /// [`RawWindowHandle`]: raw_window_handle::RawWindowHandle
59 /// [`Surface::new`]: crate::Surface::new
60 window_handle: RawWindowHandle,
61 },
62
63 /// The [`RawWindowHandle`] passed into [`Surface::new`] is missing necessary fields.
64 ///
65 /// [`RawWindowHandle`]: raw_window_handle::RawWindowHandle
66 /// [`Surface::new`]: crate::Surface::new
67 IncompleteWindowHandle,
68
69 /// The [`RawDisplayHandle`] passed into [`Context::new`] is missing necessary fields.
70 ///
71 /// [`RawDisplayHandle`]: raw_window_handle::RawDisplayHandle
72 /// [`Context::new`]: crate::Context::new
73 IncompleteDisplayHandle,
74
75 /// The provided size is outside of the range supported by the backend.
76 SizeOutOfRange {
77 /// The width that was out of range.
78 width: NonZeroU32,
79
80 /// The height that was out of range.
81 height: NonZeroU32,
82 },
83
84 /// The provided damage rect is outside of the range supported by the backend.
85 DamageOutOfRange {
86 /// The damage rect that was out of range.
87 rect: crate::Rect,
88 },
89
90 /// A platform-specific backend error occurred.
91 ///
92 /// The first field provides a human-readable description of the error. The second field
93 /// provides the actual error that occurred. Note that the second field is, under the hood,
94 /// a private wrapper around the actual error, preventing the user from downcasting to the
95 /// actual error type.
96 PlatformError(Option<String>, Option<Box<dyn Error>>),
97
98 /// This function is unimplemented on this platform.
99 Unimplemented,
100}
101
102impl fmt::Display for SoftBufferError {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 match self {
105 Self::UnsupportedDisplayPlatform {
106 human_readable_display_platform_name,
107 display_handle,
108 } => write!(
109 f,
110 "The provided display returned an unsupported platform: {}.\nDisplay handle: {:?}",
111 human_readable_display_platform_name, display_handle
112 ),
113 Self::UnsupportedWindowPlatform {
114 human_readable_window_platform_name,
115 human_readable_display_platform_name,
116 window_handle,
117 } => write!(
118 f,
119 "The provided window returned an unsupported platform: {}, {}.\nWindow handle: {:?}",
120 human_readable_window_platform_name, human_readable_display_platform_name, window_handle
121 ),
122 Self::IncompleteWindowHandle => write!(f, "The provided window handle is null."),
123 Self::IncompleteDisplayHandle => write!(f, "The provided display handle is null."),
124 Self::SizeOutOfRange { width, height } => write!(
125 f,
126 "Surface size {width}x{height} out of range for backend.",
127 ),
128 Self::PlatformError(msg, None) => write!(f, "Platform error: {msg:?}"),
129 Self::PlatformError(msg, Some(err)) => write!(f, "Platform error: {msg:?}: {err}"),
130 Self::DamageOutOfRange { rect } => write!(
131 f,
132 "Damage rect {}x{} at ({}, {}) out of range for backend.",
133 rect.width, rect.height, rect.x, rect.y
134 ),
135 Self::Unimplemented => write!(f, "This function is unimplemented on this platform."),
136 }
137 }
138}
139
140impl std::error::Error for SoftBufferError {}
141
142/// Convenient wrapper to cast errors into SoftBufferError.
143pub(crate) trait SwResultExt<T> {
144 fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError>;
145}
146
147impl<T, E: std::error::Error + 'static> SwResultExt<T> for Result<T, E> {
148 fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError> {
149 self.map_err(|e: E| {
150 SoftBufferError::PlatformError(Some(msg.into()), Some(Box::new(LibraryError(e))))
151 })
152 }
153}
154
155impl<T> SwResultExt<T> for Option<T> {
156 fn swbuf_err(self, msg: impl Into<String>) -> Result<T, SoftBufferError> {
157 self.ok_or_else(|| SoftBufferError::PlatformError(Some(msg.into()), None))
158 }
159}
160
161/// A wrapper around a library error.
162///
163/// This prevents `x11-dl` and `x11rb` from becoming public dependencies, since users cannot downcast
164/// to this type.
165struct LibraryError<E>(E);
166
167impl<E: fmt::Debug> fmt::Debug for LibraryError<E> {
168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169 fmt::Debug::fmt(&self.0, f)
170 }
171}
172
173impl<E: fmt::Display> fmt::Display for LibraryError<E> {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 fmt::Display::fmt(&self.0, f)
176 }
177}
178
179impl<E: fmt::Debug + fmt::Display> std::error::Error for LibraryError<E> {}
180