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