ark_std/io/error.rs
1use crate::boxed::Box;
2use crate::convert::From;
3use crate::error;
4use crate::fmt;
5
6/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
7/// associated traits.
8///
9/// Errors mostly originate from the underlying OS, but custom instances of
10/// `Error` can be created with crafted error messages and a particular value of
11/// [`ErrorKind`].
12///
13/// [`Read`]: crate::io::Read
14/// [`Write`]: crate::io::Write
15/// [`Seek`]: crate::io::Seek
16pub struct Error {
17 repr: Repr,
18}
19
20pub type Result<T> = core::result::Result<T, Error>;
21
22impl fmt::Debug for Error {
23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24 fmt::Debug::fmt(&self.repr, f)
25 }
26}
27
28enum Repr {
29 Simple(ErrorKind),
30 Custom(Box<Custom>),
31}
32
33#[derive(Debug)]
34struct Custom {
35 kind: ErrorKind,
36 error: Box<dyn error::Error + Send + Sync>,
37}
38
39/// A list specifying general categories of I/O error.
40///
41/// This list is intended to grow over time and it is not recommended to
42/// exhaustively match against it.
43///
44/// It is used with the [`io::Error`] type.
45///
46/// [`io::Error`]: Error
47#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
48#[allow(deprecated)]
49#[non_exhaustive]
50pub enum ErrorKind {
51 /// An entity was not found, often a file.
52 NotFound,
53 /// The operation lacked the necessary privileges to complete.
54 PermissionDenied,
55 /// The connection was refused by the remote server.
56 ConnectionRefused,
57 /// The connection was reset by the remote server.
58 ConnectionReset,
59 /// The connection was aborted (terminated) by the remote server.
60 ConnectionAborted,
61 /// The network operation failed because it was not connected yet.
62 NotConnected,
63 /// A socket address could not be bound because the address is already in
64 /// use elsewhere.
65 AddrInUse,
66 /// A nonexistent interface was requested or the requested address was not
67 /// local.
68 AddrNotAvailable,
69 /// The operation failed because a pipe was closed.
70 BrokenPipe,
71 /// An entity already exists, often a file.
72 AlreadyExists,
73 /// The operation needs to block to complete, but the blocking operation was
74 /// requested to not occur.
75 WouldBlock,
76 /// A parameter was incorrect.
77 InvalidInput,
78 /// Data not valid for the operation were encountered.
79 ///
80 /// Unlike [`InvalidInput`], this typically means that the operation
81 /// parameters were valid, however the error was caused by malformed
82 /// input data.
83 ///
84 /// For example, a function that reads a file into a string will error with
85 /// `InvalidData` if the file's contents are not valid UTF-8.
86 ///
87 /// [`InvalidInput`]: ErrorKind::InvalidInput
88 InvalidData,
89 /// The I/O operation's timeout expired, causing it to be canceled.
90 TimedOut,
91 /// An error returned when an operation could not be completed because a
92 /// call to [`write`] returned [`Ok(0)`].
93 ///
94 /// This typically means that an operation could only succeed if it wrote a
95 /// particular number of bytes but only a smaller number of bytes could be
96 /// written.
97 ///
98 /// [`write`]: crate::io::Write::write
99 /// [`Ok(0)`]: Ok
100 WriteZero,
101 /// This operation was interrupted.
102 ///
103 /// Interrupted operations can typically be retried.
104 Interrupted,
105 /// Any I/O error not part of this list.
106 ///
107 /// Errors that are `Other` now may move to a different or a new
108 /// [`ErrorKind`] variant in the future. It is not recommended to match
109 /// an error against `Other` and to expect any additional characteristics,
110 /// e.g., a specific [`Error::raw_os_error`] return value.
111 Other,
112
113 /// An error returned when an operation could not be completed because an
114 /// "end of file" was reached prematurely.
115 ///
116 /// This typically means that an operation could only succeed if it read a
117 /// particular number of bytes but only a smaller number of bytes could be
118 /// read.
119 UnexpectedEof,
120}
121
122impl ErrorKind {
123 pub(crate) fn as_str(&self) -> &'static str {
124 match *self {
125 ErrorKind::NotFound => "entity not found",
126 ErrorKind::PermissionDenied => "permission denied",
127 ErrorKind::ConnectionRefused => "connection refused",
128 ErrorKind::ConnectionReset => "connection reset",
129 ErrorKind::ConnectionAborted => "connection aborted",
130 ErrorKind::NotConnected => "not connected",
131 ErrorKind::AddrInUse => "address in use",
132 ErrorKind::AddrNotAvailable => "address not available",
133 ErrorKind::BrokenPipe => "broken pipe",
134 ErrorKind::AlreadyExists => "entity already exists",
135 ErrorKind::WouldBlock => "operation would block",
136 ErrorKind::InvalidInput => "invalid input parameter",
137 ErrorKind::InvalidData => "invalid data",
138 ErrorKind::TimedOut => "timed out",
139 ErrorKind::WriteZero => "write zero",
140 ErrorKind::Interrupted => "operation interrupted",
141 ErrorKind::Other => "other os error",
142 ErrorKind::UnexpectedEof => "unexpected end of file",
143 }
144 }
145}
146
147/// Intended for use for errors not exposed to the user, where allocating onto
148/// the heap (for normal construction via Error::new) is too costly.
149impl From<ErrorKind> for Error {
150 /// Converts an [`ErrorKind`] into an [`Error`].
151 ///
152 /// This conversion allocates a new error with a simple representation of error kind.
153 ///
154 /// # Examples
155 ///
156 /// ```
157 /// use ark_std::io::{Error, ErrorKind};
158 ///
159 /// let not_found = ErrorKind::NotFound;
160 /// let error = Error::from(not_found);
161 /// assert_eq!("entity not found", format!("{}", error));
162 /// ```
163 #[inline]
164 fn from(kind: ErrorKind) -> Error {
165 Error {
166 repr: Repr::Simple(kind),
167 }
168 }
169}
170
171impl Error {
172 /// Creates a new I/O error from a known kind of error as well as an
173 /// arbitrary error payload.
174 ///
175 /// This function is used to generically create I/O errors which do not
176 /// originate from the OS itself. The `error` argument is an arbitrary
177 /// payload which will be contained in this [`Error`].
178 ///
179 /// # Examples
180 ///
181 /// ```
182 /// use ark_std::io::{Error, ErrorKind};
183 ///
184 /// // errors can be created from strings
185 /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
186 ///
187 /// // errors can also be created from other errors
188 /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
189 /// ```
190 pub fn new<E>(kind: ErrorKind, error: E) -> Error
191 where
192 E: Into<Box<dyn error::Error + Send + Sync>>,
193 {
194 Self::_new(kind, error.into())
195 }
196
197 fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error {
198 Error {
199 repr: Repr::Custom(Box::new(Custom { kind, error })),
200 }
201 }
202
203 pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> {
204 match self.repr {
205 Repr::Simple(..) => None,
206 Repr::Custom(ref c) => Some(&*c.error),
207 }
208 }
209
210 pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> {
211 match self.repr {
212 Repr::Simple(..) => None,
213 Repr::Custom(ref mut c) => Some(&mut *c.error),
214 }
215 }
216
217 /// Consumes the `Error`, returning its inner error (if any).
218 ///
219 /// If this [`Error`] was constructed via [`new`] then this function will
220 /// return [`Some`], otherwise it will return [`None`].
221 ///
222 /// [`new`]: Error::new
223 pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> {
224 match self.repr {
225 Repr::Simple(..) => None,
226 Repr::Custom(c) => Some(c.error),
227 }
228 }
229
230 /// Returns the corresponding [`ErrorKind`] for this error.
231 pub fn kind(&self) -> ErrorKind {
232 match self.repr {
233 Repr::Custom(ref c) => c.kind,
234 Repr::Simple(kind) => kind,
235 }
236 }
237}
238
239impl fmt::Debug for Repr {
240 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
241 match *self {
242 Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
243 Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
244 }
245 }
246}
247
248impl fmt::Display for Error {
249 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
250 match self.repr {
251 Repr::Custom(ref c) => c.error.fmt(fmt),
252 Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
253 }
254 }
255}
256
257impl error::Error for Error {
258 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
259 match self.repr {
260 Repr::Simple(..) => None,
261 Repr::Custom(ref c) => c.error.source(),
262 }
263 }
264}
265
266fn _assert_error_is_sync_send() {
267 fn _is_sync_send<T: Sync + Send>() {}
268 _is_sync_send::<Error>();
269}