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}