1use std::fmt::Display;
2
3use crate::Result;
4use crate::windows::{
5 ERROR_ACCESS_DENIED, ERROR_GEN_FAILURE, ERROR_INSUFFICIENT_BUFFER, ERROR_INVALID_PARAMETER,
6 ERROR_NOT_SUPPORTED, ERROR_SUCCESS, WIN32_ERROR,
7};
8
9macro_rules! codes {
10 (
11 $(
12 ( $code:ident, $text:literal ),
13 )*
14 ) => {
15 &[
16 $(
17 ($code, stringify!($code), $text),
18 )*
19 ]
20 };
21}
22
23static CODES: &[(WIN32_ERROR, &str, &str)] = codes![
24 (ERROR_SUCCESS, "The function succeeded"),
25 (
26 ERROR_INVALID_PARAMETER,
27 "The combination of parameters and flags that are specified is invalid."
28 ),
29 (
30 ERROR_NOT_SUPPORTED,
31 "The system is not running a graphics driver that was written according to the Windows Display Driver Model (WDDM). The function is only supported on a system with a WDDM driver running."
32 ),
33 (
34 ERROR_ACCESS_DENIED,
35 "The caller does not have access to the console session. This error occurs if the calling process does not have access to the current desktop or is running on a remote session."
36 ),
37 (ERROR_GEN_FAILURE, "An unspecified error occurred."),
38 (
39 ERROR_INSUFFICIENT_BUFFER,
40 "The supplied path and mode buffer are too small."
41 ),
42];
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
46pub struct Error {
47 pub(crate) win32_error: Win32Error,
48 pub(crate) function: &'static str,
49}
50
51impl Error {
52 pub(crate) fn new(win32_error: impl Into<Win32Error>, function: &'static str) -> Self {
53 win32_error.into().to_error(function)
54 }
55
56 #[must_use]
58 pub fn win32_error(self) -> Win32Error {
59 self.win32_error
60 }
61
62 #[must_use]
64 pub fn function(self) -> &'static str {
65 self.function
66 }
67
68 #[cfg(feature = "dump")]
69 #[must_use]
70 pub(crate) fn is_ok(self) -> bool {
71 self.win32_error.is_ok()
72 }
73
74 #[cfg(feature = "dump")]
75 #[must_use]
76 pub(crate) fn is_err(&self) -> bool {
77 self.win32_error.is_err()
78 }
79
80 pub(crate) fn to_result<T>(self, value: T) -> Result<T> {
81 self.to_result_with(|| value)
82 }
83
84 pub(crate) fn to_result_with<T>(self, f: impl FnOnce() -> T) -> Result<T> {
85 if self.win32_error.is_ok() {
86 Ok(f())
87 } else {
88 Err(self)
89 }
90 }
91}
92
93impl std::error::Error for Error {}
94
95impl Display for Error {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 write!(f, "{}: {}", self.function, self.win32_error)
98 }
99}
100
101#[derive(Debug, Clone, Copy, PartialEq, Eq)]
103pub struct Win32Error(WIN32_ERROR);
104
105impl Win32Error {
106 #[must_use]
108 pub fn is_ok(self) -> bool {
109 self.0.is_ok()
110 }
111
112 #[must_use]
114 pub fn is_err(self) -> bool {
115 self.0.is_err()
116 }
117
118 #[must_use]
130 pub fn code_number(self) -> u32 {
131 self.0.0
132 }
133
134 #[must_use]
147 pub fn code_str_and_text(self) -> Option<(&'static str, &'static str)> {
148 CODES
149 .iter()
150 .find_map(|(code, code_str, text)| (self.0 == *code).then_some((*code_str, *text)))
151 }
152
153 fn to_error(self, function: &'static str) -> Error {
154 Error {
155 win32_error: self,
156 function,
157 }
158 }
159}
160
161impl From<WIN32_ERROR> for Win32Error {
162 fn from(value: WIN32_ERROR) -> Self {
163 Win32Error(value)
164 }
165}
166
167impl From<u32> for Win32Error {
168 fn from(value: u32) -> Self {
169 Win32Error::from(WIN32_ERROR(value))
170 }
171}
172
173impl From<i32> for Win32Error {
174 fn from(value: i32) -> Self {
175 Win32Error::from(value.cast_unsigned())
176 }
177}
178
179impl Display for Win32Error {
180 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
181 match self.code_str_and_text() {
182 Some((code_str, text)) => write!(f, "{code_str} - {text}"),
183 None => write!(f, "{} - Unknown error", self.code_number()),
184 }
185 }
186}