Skip to main content

error_repr/
os.rs

1//!
2#[cfg(feature = "std")]
3use crate::kind::FromIoKind;
4use crate::kind::{ErrorKind, FromRawOsError};
5
6/// Convience trait for implementing [`FromRawOsError`] and [`FromIoKind`]
7pub trait FromOsError: ErrorKind {
8    /// COnstructs `Self` from an [`OsError`]
9    fn from_os_error(err: OsError) -> Self;
10}
11
12impl<E: FromOsError> FromRawOsError for E {
13    fn from_raw_os_error(raw: crate::RawOsError) -> Self {
14        Self::from_os_error(OsError::from_raw_os_error(raw))
15    }
16}
17
18
19#[cfg(feature = "std")]
20impl<E: FromOsError> FromIoKind for E {
21    fn from_io_error_kind(kind: std::io::ErrorKind) -> Self {
22        Self::from_os_error(OsError::from_io_error_kind(kind))
23    }
24}
25
26
27/// Variant for encoding most os errors as a generic enum that can be matched upon in code - suitable for implementing [`FromRawOsError`]
28///
29/// [`OsError`] itself implements [`ErrorKind`] and [`FromRawOsError`]. However, it does not implement or [`IntoIoKind`][crate::kind::IntoIoKind]
30///
31#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
32#[non_exhaustive]
33pub enum OsError {
34    #[doc(hidden)]
35    __Uncategorized,
36    /// Other errors not generated. Note that this is not produced by the impl for [`FromRawOsError`]
37    Other,
38    /// Permission Denied
39    PermissionDenied,
40    /// An Object was not found
41    NotFound,
42    /// A Process was not found
43    NoSuchProcess,
44    /// System Call interrupted by signal/remote action
45    Interrupted,
46    /// Input/Output Error
47    InputOutputError,
48    /// A name, a record, or list was too large for a system call
49    TooBig,
50    /// An process being spawned refers to an executable file that cannot be read
51    ExecFormatError,
52    /// A Handle or File Descriptor is invalid/wrong type
53    InvalidHandle,
54    /// A Child process was not found
55    NoChild,
56    /// An operation that was required not to block would have blocked
57    WouldBlock,
58    /// Memory is unavailable or cannot be allocated
59    NoMemory,
60    /// A memory address passed to a system call was invalid/not mapped
61    InvalidMemory,
62    /// A different kind of device was required
63    WrongDeviceKind,
64    /// An Object being accessed was Busy
65    Busy,
66    /// An object that was required not to exist was located
67    ObjectExists,
68    /// An operation crosses devices when it is required not to
69    CrossDevice,
70    /// A device being identified does not exist
71    NoSuchDevice,
72    /// An object being used as a directory was not a directory
73    NotADirectory,
74    /// An object that is required not to be a directory was a directory
75    IsADirectory,
76    /// Invalid Argument/Operation
77    InvalidArgument,
78    /// A Global Handle Limit was exceeded
79    GlobalHandleExhaustion,
80    /// A Local Handle Limit was exceeded
81    HandleExhaustion,
82    /// Invalid extended operation
83    Ioctl,
84    /// An executable file is busy
85    TextFileBusy,
86    /// No Space Left on Device
87    NoSpaceLeft,
88    /// Seek on Non-Seekable Object
89    InvalidSeek,
90    /// Read-Only Filesystem
91    ReadOnlyFilesystem,
92    /// Too many links to the same object
93    TooManyLinks,
94    /// Symbolic Link Loop or excessive symbolic link chain
95    SymbolicLinkChain,
96    /// Broken Pipe
97    BrokenPipe,
98    /// Domain Error
99    DomainError,
100    /// Range Error
101    RangeError,
102    /// Deadlock (Avoided)
103    Deadlock,
104    /// A resource other than handle count, is exhausted
105    ResourceExhaustion,
106
107    /// Unsupported System Call
108    UnsupportedSystemOp,
109
110    /// Connection Refused
111    ConnectionRefused,
112
113    /// Connection Reset
114    ConnectionReset,
115
116    /// Invalid Filename
117    InvalidFilename,
118    /// Operation In-progress
119    InProgress,
120    /// Quota Exceeded
121    QuotaExceeded,
122    
123    /// Destination Host Unreachable
124    HostUnreachable,
125    /// Destination Network Unreachable
126    NetworkUnreachable,
127    /// Connection Aborted
128    ConnectionAborted,
129    /// Socket not connected
130    NotConnected,
131    /// Bind address in use
132    AddrInUse,
133    /// Bind address not available
134    AddrNotAvailable,
135    /// Network down
136    NetworkDown,
137    /// Invalid Data
138    InvalidData,
139    /// Operation timed out
140    TimedOut,
141    /// Stale File handle
142    StaleNetworkFileHandle,
143    /// Directory not empty
144    DirectoryNotEmpty,
145    /// Unexpected Eof
146    UnexpectedEof,
147    /// Write returned zero
148    WriteZero,
149
150    /// Operation Already In progress
151    AlreadyInProgress,
152}
153
154impl core::fmt::Display for OsError {
155    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
156        match self {
157            OsError::__Uncategorized => f.write_str("Uncategorized Error"),
158            OsError::Other => f.write_str("Other Error"),
159            OsError::PermissionDenied => f.write_str("Permission Denied"),
160            OsError::NotFound => f.write_str("Object not found"),
161            OsError::NoSuchProcess => f.write_str("No such process"),
162            OsError::Interrupted => f.write_str("Interrupted"),
163            OsError::InputOutputError => f.write_str("I/O Error"),
164            OsError::TooBig => f.write_str("Object too big"),
165            OsError::ExecFormatError => f.write_str("Executable format error"),
166            OsError::InvalidHandle => f.write_str("Invalid Handle/Descriptor"),
167            OsError::NoChild => f.write_str("No Child Found"),
168            OsError::WouldBlock => f.write_str("Operation would block"),
169            OsError::NoMemory => f.write_str("Out of memory"),
170            OsError::InvalidMemory => f.write_str("Invalid Memory"),
171            OsError::WrongDeviceKind => f.write_str("Wrong Device Kind"),
172            OsError::Busy => f.write_str("Device or Object Busy"),
173            OsError::ObjectExists => f.write_str("Object Exists"),
174            OsError::CrossDevice => f.write_str("Operation crosses devices"),
175            OsError::NoSuchDevice => f.write_str("No such device"),
176            OsError::NotADirectory => f.write_str("Not a Directory"),
177            OsError::IsADirectory => f.write_str("Is a Directory"),
178            OsError::InvalidArgument => f.write_str("Invalid Argument"),
179            OsError::GlobalHandleExhaustion => f.write_str("Too many Global Handles/Descriptors"),
180            OsError::HandleExhaustion => f.write_str("Too many Local Handles/Descriptors"),
181            OsError::Ioctl => f.write_str("Invalid Ioctl for device"),
182            OsError::TextFileBusy => f.write_str("Executable File Busy"),
183            OsError::NoSpaceLeft => f.write_str("No Space Left on Device"),
184            OsError::InvalidSeek => f.write_str("Invalid Seek on Non-seekable Handle"),
185            OsError::ReadOnlyFilesystem => f.write_str("Read-only Filesystem"),
186            OsError::SymbolicLinkChain => f.write_str("Symbolic Link Loop or Chain"),
187            OsError::BrokenPipe => f.write_str("Broken Pipe"),
188            OsError::UnsupportedSystemOp => f.write_str("Unsupported System Call"),
189            OsError::TooManyLinks => f.write_str("Too many links"),
190            OsError::DomainError => f.write_str("Domain Error"),
191            OsError::RangeError => f.write_str("Output out of range"),
192            OsError::Deadlock => f.write_str("Deadlock Detected"),
193            OsError::ResourceExhaustion => f.write_str("Other Resource Exhaustion"),
194            OsError::ConnectionRefused => f.write_str("Connection Refused"),
195            OsError::ConnectionReset => f.write_str("Connection Reset"),
196            OsError::InvalidFilename => f.write_str("Invalid File Name"),
197            OsError::InProgress => f.write_str("Operation In Progress"),
198            OsError::QuotaExceeded => f.write_str("Quota/Resource Limit Exceeded"),
199            OsError::HostUnreachable => f.write_str("Destination Host Unreachable"),
200            OsError::NetworkUnreachable => f.write_str("Destination Network Unreachable"),
201            OsError::ConnectionAborted => f.write_str("Connection Aborted"),
202            OsError::NotConnected => f.write_str("Not Connected"),
203            OsError::AddrInUse => f.write_str("Address In Use"),
204            OsError::AddrNotAvailable => f.write_str("Address Not Available"),
205            OsError::NetworkDown => f.write_str("Network Down"),
206            OsError::InvalidData => f.write_str("Invalid Data"),
207            OsError::TimedOut => f.write_str("Operation Timed Out"),
208            OsError::StaleNetworkFileHandle => f.write_str("Stale File Handle"),
209            OsError::DirectoryNotEmpty => f.write_str("Directory Not Empty"),
210            OsError::UnexpectedEof => f.write_str("Unexpected Eof"),
211            OsError::WriteZero => f.write_str("Write returned 0"),
212            OsError::AlreadyInProgress => f.write_str(" Operation Already Pending"),
213        }
214    }
215}
216
217impl ErrorKind for OsError {
218    const OTHER: Self = OsError::Other;
219    fn uncategorized() -> Self {
220        Self::__Uncategorized
221    }
222}
223
224impl FromRawOsError for OsError {
225    fn from_raw_os_error(raw: crate::RawOsError) -> Self {
226        os_error(raw)
227    }
228}
229
230#[cfg(feature = "std")]
231impl FromIoKind for OsError {
232    fn from_io_error_kind(kind: std::io::ErrorKind) -> Self {
233        match kind {
234            std::io::ErrorKind::NotFound => OsError::NotFound,
235            std::io::ErrorKind::PermissionDenied => OsError::PermissionDenied,
236            std::io::ErrorKind::ConnectionRefused => OsError::ConnectionRefused,
237            std::io::ErrorKind::ConnectionReset => OsError::ConnectionReset,
238            
239            std::io::ErrorKind::BrokenPipe => OsError::BrokenPipe,
240            std::io::ErrorKind::AlreadyExists => OsError::ObjectExists,
241            std::io::ErrorKind::WouldBlock => OsError::WouldBlock,
242            std::io::ErrorKind::NotADirectory => OsError::NotADirectory,
243            std::io::ErrorKind::IsADirectory => OsError::IsADirectory,
244            std::io::ErrorKind::ReadOnlyFilesystem => OsError::ReadOnlyFilesystem,
245            std::io::ErrorKind::InvalidInput => OsError::InvalidArgument,
246            std::io::ErrorKind::StorageFull => OsError::NoSpaceLeft,
247            std::io::ErrorKind::NotSeekable => OsError::InvalidSeek,
248            std::io::ErrorKind::FileTooLarge => OsError::TooBig,
249            std::io::ErrorKind::ResourceBusy => OsError::Busy,
250            std::io::ErrorKind::ExecutableFileBusy => OsError::TextFileBusy,
251            std::io::ErrorKind::Deadlock => OsError::Deadlock,
252            std::io::ErrorKind::CrossesDevices => OsError::CrossDevice,
253            std::io::ErrorKind::TooManyLinks => OsError::TooManyLinks,
254            std::io::ErrorKind::ArgumentListTooLong => OsError::TooBig,
255            std::io::ErrorKind::Interrupted => OsError::Interrupted,
256            std::io::ErrorKind::Unsupported => OsError::UnsupportedSystemOp,
257            std::io::ErrorKind::OutOfMemory => OsError::NoMemory,
258            #[cfg(feature = "nightly-io_error_more")]
259            std::io::ErrorKind::FilesystemLoop => OsError::SymbolicLinkChain,
260            #[cfg(feature = "nightly-io_error_more")]
261            std::io::ErrorKind::InProgress => OsError::InProgress,
262            std::io::ErrorKind::QuotaExceeded => OsError::QuotaExceeded,
263            std::io::ErrorKind::InvalidFilename => OsError::InvalidFilename,
264            std::io::ErrorKind::UnexpectedEof => OsError::UnexpectedEof,
265            std::io::ErrorKind::HostUnreachable => OsError::HostUnreachable,
266            std::io::ErrorKind::NetworkUnreachable => OsError::NetworkUnreachable,
267            std::io::ErrorKind::ConnectionAborted => OsError::ConnectionAborted,
268            std::io::ErrorKind::NotConnected => OsError::NotConnected,
269            std::io::ErrorKind::AddrInUse => OsError::AddrInUse,
270            std::io::ErrorKind::AddrNotAvailable => OsError::AddrNotAvailable,
271            std::io::ErrorKind::NetworkDown => OsError::NetworkDown,
272            std::io::ErrorKind::InvalidData => OsError::InvalidData,
273            std::io::ErrorKind::TimedOut => OsError::TimedOut,
274            std::io::ErrorKind::WriteZero => OsError::WriteZero,
275            std::io::ErrorKind::StaleNetworkFileHandle => OsError::StaleNetworkFileHandle,
276            std::io::ErrorKind::DirectoryNotEmpty => OsError::DirectoryNotEmpty,
277            std::io::ErrorKind::Other => OsError::Other,
278            _ => OsError::__Uncategorized,
279        }
280    }
281}
282
283cfg_select! {
284    target_os = "linux" => {
285        fn os_error(error: crate::RawOsError) -> OsError {
286            use linux_errno::*;
287            match u16::try_from(error).ok().and_then(Error::new) {
288                Some(err) => {
289                    match err {
290                        EPERM | EACCES => OsError::PermissionDenied,
291                        ENOENT  => OsError::NotFound,
292                        ESRCH => OsError::NoSuchProcess,
293                        E2BIG | EFBIG | ENAMETOOLONG => OsError::TooBig,
294                        EBADF => OsError::InvalidHandle,
295                        ECHILD => OsError::NoChild,
296                        EAGAIN => OsError::WouldBlock,
297                        ENOMEM => OsError::NoMemory,
298                        EFAULT => OsError::InvalidMemory,
299                        ENOTBLK => OsError::WrongDeviceKind,
300                        EBUSY => OsError::Busy,
301                        EXDEV => OsError::CrossDevice,
302                        ENODEV | ENXIO => OsError::NoSuchDevice,
303                        ENOTDIR => OsError::NotADirectory,
304                        EISDIR => OsError::IsADirectory,
305                        EINVAL => OsError::InvalidArgument,
306                        ENFILE => OsError::GlobalHandleExhaustion,
307                        EMFILE => OsError::HandleExhaustion,
308                        ENOTTY => OsError::Ioctl,
309                        ETXTBSY => OsError::TextFileBusy,
310                        ENOSPC => OsError::NoSpaceLeft,
311                        ESPIPE => OsError::InvalidSeek,
312                        EMLINK => OsError::TooManyLinks,
313                        EPIPE => OsError::BrokenPipe,
314                        EDOM => OsError::DomainError,
315                        ERANGE => OsError::RangeError,
316                        EDEADLK => OsError::Deadlock,
317                        ENOLCK => OsError::ResourceExhaustion,
318                        ENOSYS => OsError::UnsupportedSystemOp,
319                        EINPROGRESS => OsError::InProgress,
320                        EALREADY => OsError::AlreadyInProgress,
321                        ETIME => OsError::TimedOut,
322                        
323                        _ => OsError::__Uncategorized,
324                    }
325                }
326                None => OsError::__Uncategorized
327            }
328        }
329    }
330    target_os = "lilium" => {
331        fn os_error(error: crate::RawOsError) -> OsError {
332            todo!()
333        }
334    }
335    target_os = "windows" => {
336        fn os_error(error: crate::RawOsError) -> OsError {
337            todo!()
338        }
339    }
340    _ => {
341        fn os_error(error: crate::RawOsError) -> OsError {
342
343        }
344    }
345}