irox_safe_windows/
error.rs1use std::fmt::{Display, Formatter};
2#[cfg(windows)]
3use windows::Win32::Foundation::WIN32_ERROR;
4#[cfg(windows)]
5use windows::Win32::Networking::WinSock::WSA_ERROR;
6
7pub const WSA_INVALID_HANDLE: i32 = 6;
8pub const WSA_INVALID_PARAMETER: i32 = 87;
9pub const WSA_E_OPERATION_ABORTED: i32 = 995;
10pub const WSA_IO_INCOMPLETE: i32 = 996;
11pub const WSA_E_INTR: i32 = 10004;
12pub const WSA_E_FAULT: i32 = 10014;
13pub const WSA_E_INVAL: i32 = 10022;
14pub const WSA_E_WOULDBLOCK: i32 = 10035;
15pub const WSA_E_INPROGRESS: i32 = 10036;
16pub const WSA_E_NOTSOCK: i32 = 10038;
17pub const WSA_E_MSGSIZE: i32 = 10040;
18pub const WSA_E_OPNOTSUPP: i32 = 10045;
19pub const WSA_E_NETDOWN: i32 = 10050;
20pub const WSA_E_NETRESET: i32 = 10052;
21pub const WSA_E_CONNABORTED: i32 = 10053;
22pub const WSA_E_CONNRESET: i32 = 10054;
23pub const WSA_E_NOBUFS: i32 = 10055;
24pub const WSA_E_NOTCONN: i32 = 10057;
25pub const WSA_E_SHUTDOWN: i32 = 10058;
26pub const WSA_NOT_INITIALIZED: i32 = 10093;
27#[derive(Debug, Copy, Clone)]
28pub enum WinsockErr {
29 InvalidHandle,
30 InvalidParameter,
31}
32
33#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
34pub enum ErrorType {
35 NotFound,
36 NoConsole,
37 Network,
38 IOIncomplete,
39 #[default]
40 Other,
41}
42
43#[derive(Debug, Default, Clone, Eq, PartialEq)]
44pub struct Error {
45 msg: String,
46 err_type: ErrorType,
47}
48
49impl Display for Error {
50 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
51 write!(f, "Error: {}", self.msg)
52 }
53}
54
55impl std::error::Error for Error {}
56
57impl Error {
58 pub fn code<T>(code: u32, message: &str) -> Result<T, Error> {
59 Err(Error {
60 msg: format!("Error({code}): {message}"),
61 err_type: ErrorType::Other,
62 })
63 }
64 pub fn no_console<T>() -> Result<T, Error> {
65 Err(Error {
66 msg: "Console not allocated".to_string(),
67 err_type: ErrorType::NoConsole,
68 })
69 }
70 pub fn notfound<T>() -> Result<T, Error> {
71 Err(Error {
72 msg: "Element not found".to_string(),
73 err_type: ErrorType::NotFound,
74 })
75 }
76 pub fn msg(&self) -> &str {
77 &self.msg
78 }
79 pub fn err_type(&self) -> ErrorType {
80 self.err_type
81 }
82 pub fn is_notfound(&self) -> bool {
83 self.err_type == ErrorType::NotFound
84 }
85
86 pub fn is_ioincomplete(&self) -> bool {
87 self.err_type == ErrorType::IOIncomplete
88 }
89
90 #[cfg(windows)]
91 pub fn win32<T>(err: WIN32_ERROR) -> Result<T, Error> {
92 use windows::core::PSTR;
93 use windows::Win32::System::Diagnostics::Debug::{
94 FormatMessageA, FORMAT_MESSAGE_FROM_SYSTEM,
95 };
96 let flags = FORMAT_MESSAGE_FROM_SYSTEM;
97 let source = None;
98 let messageid = err.0;
99 let languageid = 1; let mut buf = [0u8; 1024];
102 let buffer = PSTR(buf.as_mut_ptr());
103
104 let args = None;
105 let msg = unsafe {
106 let res = FormatMessageA(flags, source, messageid, languageid, buffer, 1024, args);
107 if res > 0 {
108 std::ffi::CStr::from_bytes_until_nul(&buf)
109 .unwrap_or_default()
110 .to_string_lossy()
111 } else {
112 Default::default()
113 }
114 };
115 Error::code(err.0, msg.trim())
116 }
117}
118
119macro_rules! impl_error {
120 ($ty:path, $pre:literal) => {
121 impl From<$ty> for Error {
122 fn from(value: $ty) -> Error {
123 Error {
124 msg: format!("{}: {}", $pre, value),
125 err_type: ErrorType::Other,
126 }
127 }
128 }
129 };
130}
131
132impl_error!(std::ffi::FromBytesWithNulError, "FFI");
133impl_error!(std::ffi::FromBytesUntilNulError, "FFI");
134impl_error!(std::ffi::NulError, "FFI");
135impl_error!(std::io::Error, "IOError");
136impl_error!(irox::bits::Error, "BitsError");
137impl_error!(std::string::FromUtf16Error, "UTF16Error");
138
139#[cfg(windows)]
140impl_error!(windows::core::Error, "WindowsErr");
141
142#[cfg(windows)]
143impl From<WIN32_ERROR> for Error {
144 fn from(value: WIN32_ERROR) -> Self {
145 Error {
146 msg: format!("Win32 Error: {value:?}"),
147 err_type: ErrorType::Other,
148 }
149 }
150}
151
152#[cfg(windows)]
153impl From<WSA_ERROR> for Error {
154 fn from(value: WSA_ERROR) -> Self {
155 match value.0 {
156 WSA_NOT_INITIALIZED => Error {
157 err_type: ErrorType::Network,
158 msg: "WSANOTINITIALIZED: A successful WSAStartup call must occur before using this function".to_string()
159 },
160 WSA_E_NETDOWN => Error {
161 err_type: ErrorType::Network,
162 msg: "WSAENETDOWN: The network subsystem has failed".to_string()
163 },
164 WSA_E_NOTSOCK => Error {
165 err_type: ErrorType::Network,
166 msg: "WSAENOTSOCK: The descriptor is not a socket".to_string()
167 },
168 WSA_INVALID_HANDLE => Error {
169 err_type: ErrorType::Network,
170 msg: "WSA_INVALID_HANDLE: The hEvent parameter of the overlapped structure does not contain a valid object handle".to_string()
171 },
172 WSA_INVALID_PARAMETER => Error {
173 err_type: ErrorType::Network,
174 msg: "WSA_INVALID_PARAMETER: One of the parameters is unacceptable".to_string()
175 },
176 WSA_IO_INCOMPLETE => Error {
177 err_type: ErrorType::IOIncomplete,
178 msg: "WSA_IO_INCOMPLETE: the fWait parameter is false and the operation has not completed".to_string()
179 },
180 WSA_E_FAULT => Error {
181 err_type: ErrorType::Network,
182 msg: "WSAEFAULT: one or more of the pointers are not valid".to_string()
183 },
184 e => Error {
185 err_type: ErrorType::Other,
186 msg: format!("Unknown WSA Error code: {e}")
187 }
188 }
189 }
190}