devela/sys/os/linux/error/
error.rs1use crate::{
17 Display, Error, FmtResult, Formatter, IoError, IoErrorKind, LINUX_ERRNO as ERRNO,
18 LINUX_EXIT as EXIT, Overflow, is,
19};
20
21#[doc = crate::_tags!(linux result)]
22#[doc = crate::_doc_meta!{
24 location("sys/os/linux", type LinuxResult),
25}]
26pub type LinuxResult<T> = crate::Result<T, LinuxError>;
27
28#[doc = crate::_tags!(linux error_composite)]
29#[doc = crate::_doc_meta!{
31 location("sys/os/linux", enum LinuxError),
32 #[cfg(target_pointer_width = "32")]
33 test_size_of(LinuxError = 12|96; niche Option),
34 #[cfg(target_pointer_width = "64")]
35 test_size_of(LinuxError = 24|192; niche Option),
36}]
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
40pub enum LinuxError {
41 Sys(isize),
48 NoInput,
50 InvalidUtf8,
52 Other(&'static str),
54}
55
56impl Error for LinuxError {}
57impl Display for LinuxError {
58 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult<()> {
59 match self {
60 LinuxError::Sys(errno) => write!(f, "System error ERRNO:{errno}."),
61 LinuxError::NoInput => f.write_str("No input available"),
62 LinuxError::InvalidUtf8 => f.write_str("Invalid UTF-8 data"),
63 LinuxError::Other(s) => f.write_str(s),
64 }
65 }
66}
67
68macro_rules! _match_linux_to_io {
69 ($self:ident) => {
70 match $self {
71 LinuxError::Sys(errno) => {
72 let kind = match errno {
73 ERRNO::EPERM => IoErrorKind::PermissionDenied,
74 ERRNO::ENOENT => IoErrorKind::NotFound,
75 ERRNO::EINTR => IoErrorKind::Interrupted,
76 ERRNO::EIO => IoErrorKind::Other,
77 ERRNO::ENXIO => IoErrorKind::NotFound,
78 ERRNO::EAGAIN => IoErrorKind::WouldBlock,
79 ERRNO::ENOMEM => IoErrorKind::OutOfMemory,
80 ERRNO::EACCES => IoErrorKind::PermissionDenied,
81 ERRNO::EFAULT => IoErrorKind::InvalidInput,
82 ERRNO::EBUSY => IoErrorKind::ResourceBusy,
83 ERRNO::EEXIST => IoErrorKind::AlreadyExists,
84 ERRNO::ENOTDIR => IoErrorKind::NotADirectory,
85 ERRNO::EISDIR => IoErrorKind::IsADirectory,
86 ERRNO::EINVAL => IoErrorKind::InvalidInput,
87 ERRNO::ENOSPC => IoErrorKind::StorageFull,
88 ERRNO::EROFS => IoErrorKind::ReadOnlyFilesystem,
89 ERRNO::EMLINK => IoErrorKind::TooManyLinks,
90 ERRNO::EPIPE => IoErrorKind::BrokenPipe,
91 ERRNO::EDOM => IoErrorKind::InvalidInput,
92 ERRNO::ERANGE => IoErrorKind::InvalidInput,
93 ERRNO::EDEADLK => IoErrorKind::Deadlock,
94 ERRNO::ENAMETOOLONG => IoErrorKind::InvalidFilename,
95 ERRNO::ENOLCK => IoErrorKind::ResourceBusy,
96 ERRNO::ENOSYS => IoErrorKind::Unsupported,
97 ERRNO::ENOTEMPTY => IoErrorKind::DirectoryNotEmpty,
98 ERRNO::ENODEV => IoErrorKind::NotFound,
101 ERRNO::ETIMEDOUT => IoErrorKind::TimedOut,
102 ERRNO::EXDEV => IoErrorKind::CrossesDevices,
103 ERRNO::ETXTBSY => IoErrorKind::ExecutableFileBusy,
104 _ => IoErrorKind::Other,
105 };
106 IoError::new(kind, "system call failed")
107 }
108 LinuxError::NoInput => IoError::new(IoErrorKind::UnexpectedEof, "no input available"),
109 LinuxError::InvalidUtf8 => IoError::new(IoErrorKind::InvalidData, "invalid UTF-8 data"),
110 LinuxError::Other(s) => IoError::new(IoErrorKind::Other, s),
111 }
112 };
113}
114macro_rules! _match_io_to_linux {
115 ($err:ident) => {
116 match $err.kind() {
117 IoErrorKind::PermissionDenied => LinuxError::Sys(ERRNO::EACCES),
118 IoErrorKind::NotFound => LinuxError::Sys(ERRNO::ENOENT),
119 IoErrorKind::Interrupted => LinuxError::Sys(ERRNO::EINTR),
120 IoErrorKind::WouldBlock => LinuxError::Sys(ERRNO::EAGAIN),
121 IoErrorKind::OutOfMemory => LinuxError::Sys(ERRNO::ENOMEM),
122 IoErrorKind::InvalidInput => LinuxError::Sys(ERRNO::EINVAL),
123 IoErrorKind::StorageFull => LinuxError::Sys(ERRNO::ENOSPC),
124 IoErrorKind::BrokenPipe => LinuxError::Sys(ERRNO::EPIPE),
125 IoErrorKind::UnexpectedEof => LinuxError::NoInput,
126 IoErrorKind::InvalidData => LinuxError::InvalidUtf8,
127 _ => LinuxError::Sys(ERRNO::EIO), }
129 };
130}
131#[rustfmt::skip]
132impl LinuxError {
133 #[cfg(feature = "std")]
138 pub fn to_io(self) -> IoError { _match_linux_to_io!(self) }
139 #[cfg(not(feature = "std"))]
141 pub const fn to_io(self) -> IoError { _match_linux_to_io!(self) }
142
143 #[cfg(feature = "std")]
148 pub fn from_io(err: IoError) -> LinuxError { _match_io_to_linux!(err) }
149 #[cfg(not(feature = "std"))]
151 pub const fn from_io(err: IoError) -> LinuxError { _match_io_to_linux!(err) }
152}
153impl From<LinuxError> for IoError {
154 fn from(err: LinuxError) -> Self {
155 err.to_io()
156 }
157}
158impl From<IoError> for LinuxError {
159 fn from(err: IoError) -> Self {
160 LinuxError::from_io(err)
161 }
162}
163
164impl From<Overflow> for LinuxError {
165 fn from(_err: Overflow) -> Self {
166 LinuxError::Other("Overflow.")
167 }
168}
169
170impl LinuxError {
171 pub const fn to_exit_code(self) -> i32 {
175 let code = self.to_raw_exit_code();
176 is![code >= EXIT::SUCCESS && code <= EXIT::MAX, code, EXIT::INTERNAL_ERROR]
177 }
178
179 pub const fn to_raw_exit_code(self) -> i32 {
181 match self {
182 LinuxError::Sys(errno) => {
183 match errno {
184 ERRNO::EPERM => EXIT::NOPERM,
185 ERRNO::ENOENT => EXIT::NOINPUT,
186 ERRNO::EACCES => EXIT::NOPERM,
187 ERRNO::EINVAL => EXIT::USAGE,
188 ERRNO::ENOSYS => EXIT::SOFTWARE,
189 ERRNO::ENOMEM => EXIT::OSERR,
190 ERRNO::EIO => EXIT::IOERR,
191 ERRNO::ENFILE | ERRNO::EMFILE => EXIT::OSFILE,
192 ERRNO::EEXIST => EXIT::CANTCREAT,
193 ERRNO::ENOTDIR => EXIT::DATAERR,
194 ERRNO::EISDIR => EXIT::DATAERR,
195 ERRNO::ETIMEDOUT => EXIT::TEMPFAIL,
196 _ => EXIT::OSERR,
198 }
199 }
200 LinuxError::NoInput => EXIT::NOINPUT,
201 LinuxError::InvalidUtf8 => EXIT::DATAERR,
202 LinuxError::Other(_s) => EXIT::FAILURE,
203 }
204 }
205}