1 | #[cfg (test)] |
2 | mod tests; |
3 | |
4 | #[cfg (all(target_pointer_width = "64" , not(target_os = "uefi" )))] |
5 | mod repr_bitpacked; |
6 | #[cfg (all(target_pointer_width = "64" , not(target_os = "uefi" )))] |
7 | use repr_bitpacked::Repr; |
8 | |
9 | #[cfg (any(not(target_pointer_width = "64" ), target_os = "uefi" ))] |
10 | mod repr_unpacked; |
11 | #[cfg (any(not(target_pointer_width = "64" ), target_os = "uefi" ))] |
12 | use repr_unpacked::Repr; |
13 | |
14 | use crate::{error, fmt, result, sys}; |
15 | |
16 | /// A specialized [`Result`] type for I/O operations. |
17 | /// |
18 | /// This type is broadly used across [`std::io`] for any operation which may |
19 | /// produce an error. |
20 | /// |
21 | /// This typedef is generally used to avoid writing out [`io::Error`] directly and |
22 | /// is otherwise a direct mapping to [`Result`]. |
23 | /// |
24 | /// While usual Rust style is to import types directly, aliases of [`Result`] |
25 | /// often are not, to make it easier to distinguish between them. [`Result`] is |
26 | /// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias |
27 | /// will generally use `io::Result` instead of shadowing the [prelude]'s import |
28 | /// of [`std::result::Result`][`Result`]. |
29 | /// |
30 | /// [`std::io`]: crate::io |
31 | /// [`io::Error`]: Error |
32 | /// [`Result`]: crate::result::Result |
33 | /// [prelude]: crate::prelude |
34 | /// |
35 | /// # Examples |
36 | /// |
37 | /// A convenience function that bubbles an `io::Result` to its caller: |
38 | /// |
39 | /// ``` |
40 | /// use std::io; |
41 | /// |
42 | /// fn get_string() -> io::Result<String> { |
43 | /// let mut buffer = String::new(); |
44 | /// |
45 | /// io::stdin().read_line(&mut buffer)?; |
46 | /// |
47 | /// Ok(buffer) |
48 | /// } |
49 | /// ``` |
50 | #[stable (feature = "rust1" , since = "1.0.0" )] |
51 | pub type Result<T> = result::Result<T, Error>; |
52 | |
53 | /// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and |
54 | /// associated traits. |
55 | /// |
56 | /// Errors mostly originate from the underlying OS, but custom instances of |
57 | /// `Error` can be created with crafted error messages and a particular value of |
58 | /// [`ErrorKind`]. |
59 | /// |
60 | /// [`Read`]: crate::io::Read |
61 | /// [`Write`]: crate::io::Write |
62 | /// [`Seek`]: crate::io::Seek |
63 | #[stable (feature = "rust1" , since = "1.0.0" )] |
64 | pub struct Error { |
65 | repr: Repr, |
66 | } |
67 | |
68 | #[stable (feature = "rust1" , since = "1.0.0" )] |
69 | impl fmt::Debug for Error { |
70 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
71 | fmt::Debug::fmt(&self.repr, f) |
72 | } |
73 | } |
74 | |
75 | /// Common errors constants for use in std |
76 | #[allow (dead_code)] |
77 | impl Error { |
78 | pub(crate) const INVALID_UTF8: Self = |
79 | const_error!(ErrorKind::InvalidData, "stream did not contain valid UTF-8" ); |
80 | |
81 | pub(crate) const READ_EXACT_EOF: Self = |
82 | const_error!(ErrorKind::UnexpectedEof, "failed to fill whole buffer" ); |
83 | |
84 | pub(crate) const UNKNOWN_THREAD_COUNT: Self = const_error!( |
85 | ErrorKind::NotFound, |
86 | "the number of hardware threads is not known for the target platform" , |
87 | ); |
88 | |
89 | pub(crate) const UNSUPPORTED_PLATFORM: Self = |
90 | const_error!(ErrorKind::Unsupported, "operation not supported on this platform" ); |
91 | |
92 | pub(crate) const WRITE_ALL_EOF: Self = |
93 | const_error!(ErrorKind::WriteZero, "failed to write whole buffer" ); |
94 | |
95 | pub(crate) const ZERO_TIMEOUT: Self = |
96 | const_error!(ErrorKind::InvalidInput, "cannot set a 0 duration timeout" ); |
97 | } |
98 | |
99 | #[stable (feature = "rust1" , since = "1.0.0" )] |
100 | impl From<alloc::ffi::NulError> for Error { |
101 | /// Converts a [`alloc::ffi::NulError`] into a [`Error`]. |
102 | fn from(_: alloc::ffi::NulError) -> Error { |
103 | const_error!(ErrorKind::InvalidInput, "data provided contains a nul byte" ) |
104 | } |
105 | } |
106 | |
107 | #[stable (feature = "io_error_from_try_reserve" , since = "1.78.0" )] |
108 | impl From<alloc::collections::TryReserveError> for Error { |
109 | /// Converts `TryReserveError` to an error with [`ErrorKind::OutOfMemory`]. |
110 | /// |
111 | /// `TryReserveError` won't be available as the error `source()`, |
112 | /// but this may change in the future. |
113 | fn from(_: alloc::collections::TryReserveError) -> Error { |
114 | // ErrorData::Custom allocates, which isn't great for handling OOM errors. |
115 | ErrorKind::OutOfMemory.into() |
116 | } |
117 | } |
118 | |
119 | // Only derive debug in tests, to make sure it |
120 | // doesn't accidentally get printed. |
121 | #[cfg_attr (test, derive(Debug))] |
122 | enum ErrorData<C> { |
123 | Os(RawOsError), |
124 | Simple(ErrorKind), |
125 | SimpleMessage(&'static SimpleMessage), |
126 | Custom(C), |
127 | } |
128 | |
129 | /// The type of raw OS error codes returned by [`Error::raw_os_error`]. |
130 | /// |
131 | /// This is an [`i32`] on all currently supported platforms, but platforms |
132 | /// added in the future (such as UEFI) may use a different primitive type like |
133 | /// [`usize`]. Use `as`or [`into`] conversions where applicable to ensure maximum |
134 | /// portability. |
135 | /// |
136 | /// [`into`]: Into::into |
137 | #[unstable (feature = "raw_os_error_ty" , issue = "107792" )] |
138 | pub type RawOsError = sys::RawOsError; |
139 | |
140 | // `#[repr(align(4))]` is probably redundant, it should have that value or |
141 | // higher already. We include it just because repr_bitpacked.rs's encoding |
142 | // requires an alignment >= 4 (note that `#[repr(align)]` will not reduce the |
143 | // alignment required by the struct, only increase it). |
144 | // |
145 | // If we add more variants to ErrorData, this can be increased to 8, but it |
146 | // should probably be behind `#[cfg_attr(target_pointer_width = "64", ...)]` or |
147 | // whatever cfg we're using to enable the `repr_bitpacked` code, since only the |
148 | // that version needs the alignment, and 8 is higher than the alignment we'll |
149 | // have on 32 bit platforms. |
150 | // |
151 | // (For the sake of being explicit: the alignment requirement here only matters |
152 | // if `error/repr_bitpacked.rs` is in use — for the unpacked repr it doesn't |
153 | // matter at all) |
154 | #[doc (hidden)] |
155 | #[unstable (feature = "io_const_error_internals" , issue = "none" )] |
156 | #[repr (align(4))] |
157 | #[derive (Debug)] |
158 | pub struct SimpleMessage { |
159 | pub kind: ErrorKind, |
160 | pub message: &'static str, |
161 | } |
162 | |
163 | /// Creates a new I/O error from a known kind of error and a string literal. |
164 | /// |
165 | /// Contrary to [`Error::new`], this macro does not allocate and can be used in |
166 | /// `const` contexts. |
167 | /// |
168 | /// # Example |
169 | /// ``` |
170 | /// #![feature(io_const_error)] |
171 | /// use std::io::{const_error, Error, ErrorKind}; |
172 | /// |
173 | /// const FAIL: Error = const_error!(ErrorKind::Unsupported, "tried something that never works" ); |
174 | /// |
175 | /// fn not_here() -> Result<(), Error> { |
176 | /// Err(FAIL) |
177 | /// } |
178 | /// ``` |
179 | #[rustc_macro_transparency = "semitransparent" ] |
180 | #[unstable (feature = "io_const_error" , issue = "133448" )] |
181 | #[allow_internal_unstable (hint_must_use, io_const_error_internals)] |
182 | pub macro const_error($kind:expr, $message:expr $(,)?) { |
183 | $crate::hint::must_use($crate::io::Error::from_static_message( |
184 | const { &$crate::io::SimpleMessage { kind: $kind, message: $message } }, |
185 | )) |
186 | } |
187 | |
188 | // As with `SimpleMessage`: `#[repr(align(4))]` here is just because |
189 | // repr_bitpacked's encoding requires it. In practice it almost certainly be |
190 | // already be this high or higher. |
191 | #[derive (Debug)] |
192 | #[repr (align(4))] |
193 | struct Custom { |
194 | kind: ErrorKind, |
195 | error: Box<dyn error::Error + Send + Sync>, |
196 | } |
197 | |
198 | /// A list specifying general categories of I/O error. |
199 | /// |
200 | /// This list is intended to grow over time and it is not recommended to |
201 | /// exhaustively match against it. |
202 | /// |
203 | /// It is used with the [`io::Error`] type. |
204 | /// |
205 | /// [`io::Error`]: Error |
206 | /// |
207 | /// # Handling errors and matching on `ErrorKind` |
208 | /// |
209 | /// In application code, use `match` for the `ErrorKind` values you are |
210 | /// expecting; use `_` to match "all other errors". |
211 | /// |
212 | /// In comprehensive and thorough tests that want to verify that a test doesn't |
213 | /// return any known incorrect error kind, you may want to cut-and-paste the |
214 | /// current full list of errors from here into your test code, and then match |
215 | /// `_` as the correct case. This seems counterintuitive, but it will make your |
216 | /// tests more robust. In particular, if you want to verify that your code does |
217 | /// produce an unrecognized error kind, the robust solution is to check for all |
218 | /// the recognized error kinds and fail in those cases. |
219 | #[derive (Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] |
220 | #[stable (feature = "rust1" , since = "1.0.0" )] |
221 | #[allow (deprecated)] |
222 | #[non_exhaustive ] |
223 | pub enum ErrorKind { |
224 | /// An entity was not found, often a file. |
225 | #[stable (feature = "rust1" , since = "1.0.0" )] |
226 | NotFound, |
227 | /// The operation lacked the necessary privileges to complete. |
228 | #[stable (feature = "rust1" , since = "1.0.0" )] |
229 | PermissionDenied, |
230 | /// The connection was refused by the remote server. |
231 | #[stable (feature = "rust1" , since = "1.0.0" )] |
232 | ConnectionRefused, |
233 | /// The connection was reset by the remote server. |
234 | #[stable (feature = "rust1" , since = "1.0.0" )] |
235 | ConnectionReset, |
236 | /// The remote host is not reachable. |
237 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
238 | HostUnreachable, |
239 | /// The network containing the remote host is not reachable. |
240 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
241 | NetworkUnreachable, |
242 | /// The connection was aborted (terminated) by the remote server. |
243 | #[stable (feature = "rust1" , since = "1.0.0" )] |
244 | ConnectionAborted, |
245 | /// The network operation failed because it was not connected yet. |
246 | #[stable (feature = "rust1" , since = "1.0.0" )] |
247 | NotConnected, |
248 | /// A socket address could not be bound because the address is already in |
249 | /// use elsewhere. |
250 | #[stable (feature = "rust1" , since = "1.0.0" )] |
251 | AddrInUse, |
252 | /// A nonexistent interface was requested or the requested address was not |
253 | /// local. |
254 | #[stable (feature = "rust1" , since = "1.0.0" )] |
255 | AddrNotAvailable, |
256 | /// The system's networking is down. |
257 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
258 | NetworkDown, |
259 | /// The operation failed because a pipe was closed. |
260 | #[stable (feature = "rust1" , since = "1.0.0" )] |
261 | BrokenPipe, |
262 | /// An entity already exists, often a file. |
263 | #[stable (feature = "rust1" , since = "1.0.0" )] |
264 | AlreadyExists, |
265 | /// The operation needs to block to complete, but the blocking operation was |
266 | /// requested to not occur. |
267 | #[stable (feature = "rust1" , since = "1.0.0" )] |
268 | WouldBlock, |
269 | /// A filesystem object is, unexpectedly, not a directory. |
270 | /// |
271 | /// For example, a filesystem path was specified where one of the intermediate directory |
272 | /// components was, in fact, a plain file. |
273 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
274 | NotADirectory, |
275 | /// The filesystem object is, unexpectedly, a directory. |
276 | /// |
277 | /// A directory was specified when a non-directory was expected. |
278 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
279 | IsADirectory, |
280 | /// A non-empty directory was specified where an empty directory was expected. |
281 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
282 | DirectoryNotEmpty, |
283 | /// The filesystem or storage medium is read-only, but a write operation was attempted. |
284 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
285 | ReadOnlyFilesystem, |
286 | /// Loop in the filesystem or IO subsystem; often, too many levels of symbolic links. |
287 | /// |
288 | /// There was a loop (or excessively long chain) resolving a filesystem object |
289 | /// or file IO object. |
290 | /// |
291 | /// On Unix this is usually the result of a symbolic link loop; or, of exceeding the |
292 | /// system-specific limit on the depth of symlink traversal. |
293 | #[unstable (feature = "io_error_more" , issue = "86442" )] |
294 | FilesystemLoop, |
295 | /// Stale network file handle. |
296 | /// |
297 | /// With some network filesystems, notably NFS, an open file (or directory) can be invalidated |
298 | /// by problems with the network or server. |
299 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
300 | StaleNetworkFileHandle, |
301 | /// A parameter was incorrect. |
302 | #[stable (feature = "rust1" , since = "1.0.0" )] |
303 | InvalidInput, |
304 | /// Data not valid for the operation were encountered. |
305 | /// |
306 | /// Unlike [`InvalidInput`], this typically means that the operation |
307 | /// parameters were valid, however the error was caused by malformed |
308 | /// input data. |
309 | /// |
310 | /// For example, a function that reads a file into a string will error with |
311 | /// `InvalidData` if the file's contents are not valid UTF-8. |
312 | /// |
313 | /// [`InvalidInput`]: ErrorKind::InvalidInput |
314 | #[stable (feature = "io_invalid_data" , since = "1.2.0" )] |
315 | InvalidData, |
316 | /// The I/O operation's timeout expired, causing it to be canceled. |
317 | #[stable (feature = "rust1" , since = "1.0.0" )] |
318 | TimedOut, |
319 | /// An error returned when an operation could not be completed because a |
320 | /// call to [`write`] returned [`Ok(0)`]. |
321 | /// |
322 | /// This typically means that an operation could only succeed if it wrote a |
323 | /// particular number of bytes but only a smaller number of bytes could be |
324 | /// written. |
325 | /// |
326 | /// [`write`]: crate::io::Write::write |
327 | /// [`Ok(0)`]: Ok |
328 | #[stable (feature = "rust1" , since = "1.0.0" )] |
329 | WriteZero, |
330 | /// The underlying storage (typically, a filesystem) is full. |
331 | /// |
332 | /// This does not include out of quota errors. |
333 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
334 | StorageFull, |
335 | /// Seek on unseekable file. |
336 | /// |
337 | /// Seeking was attempted on an open file handle which is not suitable for seeking - for |
338 | /// example, on Unix, a named pipe opened with `File::open`. |
339 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
340 | NotSeekable, |
341 | /// Filesystem quota or some other kind of quota was exceeded. |
342 | #[stable (feature = "io_error_quota_exceeded" , since = "1.85.0" )] |
343 | QuotaExceeded, |
344 | /// File larger than allowed or supported. |
345 | /// |
346 | /// This might arise from a hard limit of the underlying filesystem or file access API, or from |
347 | /// an administratively imposed resource limitation. Simple disk full, and out of quota, have |
348 | /// their own errors. |
349 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
350 | FileTooLarge, |
351 | /// Resource is busy. |
352 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
353 | ResourceBusy, |
354 | /// Executable file is busy. |
355 | /// |
356 | /// An attempt was made to write to a file which is also in use as a running program. (Not all |
357 | /// operating systems detect this situation.) |
358 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
359 | ExecutableFileBusy, |
360 | /// Deadlock (avoided). |
361 | /// |
362 | /// A file locking operation would result in deadlock. This situation is typically detected, if |
363 | /// at all, on a best-effort basis. |
364 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
365 | Deadlock, |
366 | /// Cross-device or cross-filesystem (hard) link or rename. |
367 | #[stable (feature = "io_error_crosses_devices" , since = "1.85.0" )] |
368 | CrossesDevices, |
369 | /// Too many (hard) links to the same filesystem object. |
370 | /// |
371 | /// The filesystem does not support making so many hardlinks to the same file. |
372 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
373 | TooManyLinks, |
374 | /// A filename was invalid. |
375 | /// |
376 | /// This error can also occur if a length limit for a name was exceeded. |
377 | #[stable (feature = "io_error_invalid_filename" , since = "1.87.0" )] |
378 | InvalidFilename, |
379 | /// Program argument list too long. |
380 | /// |
381 | /// When trying to run an external program, a system or process limit on the size of the |
382 | /// arguments would have been exceeded. |
383 | #[stable (feature = "io_error_a_bit_more" , since = "1.83.0" )] |
384 | ArgumentListTooLong, |
385 | /// This operation was interrupted. |
386 | /// |
387 | /// Interrupted operations can typically be retried. |
388 | #[stable (feature = "rust1" , since = "1.0.0" )] |
389 | Interrupted, |
390 | |
391 | /// This operation is unsupported on this platform. |
392 | /// |
393 | /// This means that the operation can never succeed. |
394 | #[stable (feature = "unsupported_error" , since = "1.53.0" )] |
395 | Unsupported, |
396 | |
397 | // ErrorKinds which are primarily categorisations for OS error |
398 | // codes should be added above. |
399 | // |
400 | /// An error returned when an operation could not be completed because an |
401 | /// "end of file" was reached prematurely. |
402 | /// |
403 | /// This typically means that an operation could only succeed if it read a |
404 | /// particular number of bytes but only a smaller number of bytes could be |
405 | /// read. |
406 | #[stable (feature = "read_exact" , since = "1.6.0" )] |
407 | UnexpectedEof, |
408 | |
409 | /// An operation could not be completed, because it failed |
410 | /// to allocate enough memory. |
411 | #[stable (feature = "out_of_memory_error" , since = "1.54.0" )] |
412 | OutOfMemory, |
413 | |
414 | /// The operation was partially successful and needs to be checked |
415 | /// later on due to not blocking. |
416 | #[unstable (feature = "io_error_inprogress" , issue = "130840" )] |
417 | InProgress, |
418 | |
419 | // "Unusual" error kinds which do not correspond simply to (sets |
420 | // of) OS error codes, should be added just above this comment. |
421 | // `Other` and `Uncategorized` should remain at the end: |
422 | // |
423 | /// A custom error that does not fall under any other I/O error kind. |
424 | /// |
425 | /// This can be used to construct your own [`Error`]s that do not match any |
426 | /// [`ErrorKind`]. |
427 | /// |
428 | /// This [`ErrorKind`] is not used by the standard library. |
429 | /// |
430 | /// Errors from the standard library that do not fall under any of the I/O |
431 | /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. |
432 | /// New [`ErrorKind`]s might be added in the future for some of those. |
433 | #[stable (feature = "rust1" , since = "1.0.0" )] |
434 | Other, |
435 | |
436 | /// Any I/O error from the standard library that's not part of this list. |
437 | /// |
438 | /// Errors that are `Uncategorized` now may move to a different or a new |
439 | /// [`ErrorKind`] variant in the future. It is not recommended to match |
440 | /// an error against `Uncategorized`; use a wildcard match (`_`) instead. |
441 | #[unstable (feature = "io_error_uncategorized" , issue = "none" )] |
442 | #[doc (hidden)] |
443 | Uncategorized, |
444 | } |
445 | |
446 | impl ErrorKind { |
447 | pub(crate) fn as_str(&self) -> &'static str { |
448 | use ErrorKind::*; |
449 | match *self { |
450 | // tidy-alphabetical-start |
451 | AddrInUse => "address in use" , |
452 | AddrNotAvailable => "address not available" , |
453 | AlreadyExists => "entity already exists" , |
454 | ArgumentListTooLong => "argument list too long" , |
455 | BrokenPipe => "broken pipe" , |
456 | ConnectionAborted => "connection aborted" , |
457 | ConnectionRefused => "connection refused" , |
458 | ConnectionReset => "connection reset" , |
459 | CrossesDevices => "cross-device link or rename" , |
460 | Deadlock => "deadlock" , |
461 | DirectoryNotEmpty => "directory not empty" , |
462 | ExecutableFileBusy => "executable file busy" , |
463 | FilesystemLoop => "filesystem loop or indirection limit (e.g. symlink loop)" , |
464 | FileTooLarge => "file too large" , |
465 | HostUnreachable => "host unreachable" , |
466 | InProgress => "in progress" , |
467 | Interrupted => "operation interrupted" , |
468 | InvalidData => "invalid data" , |
469 | InvalidFilename => "invalid filename" , |
470 | InvalidInput => "invalid input parameter" , |
471 | IsADirectory => "is a directory" , |
472 | NetworkDown => "network down" , |
473 | NetworkUnreachable => "network unreachable" , |
474 | NotADirectory => "not a directory" , |
475 | NotConnected => "not connected" , |
476 | NotFound => "entity not found" , |
477 | NotSeekable => "seek on unseekable file" , |
478 | Other => "other error" , |
479 | OutOfMemory => "out of memory" , |
480 | PermissionDenied => "permission denied" , |
481 | QuotaExceeded => "quota exceeded" , |
482 | ReadOnlyFilesystem => "read-only filesystem or storage medium" , |
483 | ResourceBusy => "resource busy" , |
484 | StaleNetworkFileHandle => "stale network file handle" , |
485 | StorageFull => "no storage space" , |
486 | TimedOut => "timed out" , |
487 | TooManyLinks => "too many links" , |
488 | Uncategorized => "uncategorized error" , |
489 | UnexpectedEof => "unexpected end of file" , |
490 | Unsupported => "unsupported" , |
491 | WouldBlock => "operation would block" , |
492 | WriteZero => "write zero" , |
493 | // tidy-alphabetical-end |
494 | } |
495 | } |
496 | } |
497 | |
498 | #[stable (feature = "io_errorkind_display" , since = "1.60.0" )] |
499 | impl fmt::Display for ErrorKind { |
500 | /// Shows a human-readable description of the `ErrorKind`. |
501 | /// |
502 | /// This is similar to `impl Display for Error`, but doesn't require first converting to Error. |
503 | /// |
504 | /// # Examples |
505 | /// ``` |
506 | /// use std::io::ErrorKind; |
507 | /// assert_eq!("entity not found" , ErrorKind::NotFound.to_string()); |
508 | /// ``` |
509 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
510 | fmt.write_str(self.as_str()) |
511 | } |
512 | } |
513 | |
514 | /// Intended for use for errors not exposed to the user, where allocating onto |
515 | /// the heap (for normal construction via Error::new) is too costly. |
516 | #[stable (feature = "io_error_from_errorkind" , since = "1.14.0" )] |
517 | impl From<ErrorKind> for Error { |
518 | /// Converts an [`ErrorKind`] into an [`Error`]. |
519 | /// |
520 | /// This conversion creates a new error with a simple representation of error kind. |
521 | /// |
522 | /// # Examples |
523 | /// |
524 | /// ``` |
525 | /// use std::io::{Error, ErrorKind}; |
526 | /// |
527 | /// let not_found = ErrorKind::NotFound; |
528 | /// let error = Error::from(not_found); |
529 | /// assert_eq!("entity not found" , format!("{error}" )); |
530 | /// ``` |
531 | #[inline ] |
532 | fn from(kind: ErrorKind) -> Error { |
533 | Error { repr: Repr::new_simple(kind) } |
534 | } |
535 | } |
536 | |
537 | impl Error { |
538 | /// Creates a new I/O error from a known kind of error as well as an |
539 | /// arbitrary error payload. |
540 | /// |
541 | /// This function is used to generically create I/O errors which do not |
542 | /// originate from the OS itself. The `error` argument is an arbitrary |
543 | /// payload which will be contained in this [`Error`]. |
544 | /// |
545 | /// Note that this function allocates memory on the heap. |
546 | /// If no extra payload is required, use the `From` conversion from |
547 | /// `ErrorKind`. |
548 | /// |
549 | /// # Examples |
550 | /// |
551 | /// ``` |
552 | /// use std::io::{Error, ErrorKind}; |
553 | /// |
554 | /// // errors can be created from strings |
555 | /// let custom_error = Error::new(ErrorKind::Other, "oh no!" ); |
556 | /// |
557 | /// // errors can also be created from other errors |
558 | /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error); |
559 | /// |
560 | /// // creating an error without payload (and without memory allocation) |
561 | /// let eof_error = Error::from(ErrorKind::UnexpectedEof); |
562 | /// ``` |
563 | #[stable (feature = "rust1" , since = "1.0.0" )] |
564 | #[inline (never)] |
565 | pub fn new<E>(kind: ErrorKind, error: E) -> Error |
566 | where |
567 | E: Into<Box<dyn error::Error + Send + Sync>>, |
568 | { |
569 | Self::_new(kind, error.into()) |
570 | } |
571 | |
572 | /// Creates a new I/O error from an arbitrary error payload. |
573 | /// |
574 | /// This function is used to generically create I/O errors which do not |
575 | /// originate from the OS itself. It is a shortcut for [`Error::new`] |
576 | /// with [`ErrorKind::Other`]. |
577 | /// |
578 | /// # Examples |
579 | /// |
580 | /// ``` |
581 | /// use std::io::Error; |
582 | /// |
583 | /// // errors can be created from strings |
584 | /// let custom_error = Error::other("oh no!" ); |
585 | /// |
586 | /// // errors can also be created from other errors |
587 | /// let custom_error2 = Error::other(custom_error); |
588 | /// ``` |
589 | #[stable (feature = "io_error_other" , since = "1.74.0" )] |
590 | pub fn other<E>(error: E) -> Error |
591 | where |
592 | E: Into<Box<dyn error::Error + Send + Sync>>, |
593 | { |
594 | Self::_new(ErrorKind::Other, error.into()) |
595 | } |
596 | |
597 | fn _new(kind: ErrorKind, error: Box<dyn error::Error + Send + Sync>) -> Error { |
598 | Error { repr: Repr::new_custom(Box::new(Custom { kind, error })) } |
599 | } |
600 | |
601 | /// Creates a new I/O error from a known kind of error as well as a constant |
602 | /// message. |
603 | /// |
604 | /// This function does not allocate. |
605 | /// |
606 | /// You should not use this directly, and instead use the `const_error!` |
607 | /// macro: `io::const_error!(ErrorKind::Something, "some_message")`. |
608 | /// |
609 | /// This function should maybe change to `from_static_message<const MSG: &'static |
610 | /// str>(kind: ErrorKind)` in the future, when const generics allow that. |
611 | #[inline ] |
612 | #[doc (hidden)] |
613 | #[unstable (feature = "io_const_error_internals" , issue = "none" )] |
614 | pub const fn from_static_message(msg: &'static SimpleMessage) -> Error { |
615 | Self { repr: Repr::new_simple_message(msg) } |
616 | } |
617 | |
618 | /// Returns an error representing the last OS error which occurred. |
619 | /// |
620 | /// This function reads the value of `errno` for the target platform (e.g. |
621 | /// `GetLastError` on Windows) and will return a corresponding instance of |
622 | /// [`Error`] for the error code. |
623 | /// |
624 | /// This should be called immediately after a call to a platform function, |
625 | /// otherwise the state of the error value is indeterminate. In particular, |
626 | /// other standard library functions may call platform functions that may |
627 | /// (or may not) reset the error value even if they succeed. |
628 | /// |
629 | /// # Examples |
630 | /// |
631 | /// ``` |
632 | /// use std::io::Error; |
633 | /// |
634 | /// let os_error = Error::last_os_error(); |
635 | /// println!("last OS error: {os_error:?}" ); |
636 | /// ``` |
637 | #[stable (feature = "rust1" , since = "1.0.0" )] |
638 | #[doc (alias = "GetLastError" )] |
639 | #[doc (alias = "errno" )] |
640 | #[must_use ] |
641 | #[inline ] |
642 | pub fn last_os_error() -> Error { |
643 | Error::from_raw_os_error(sys::os::errno()) |
644 | } |
645 | |
646 | /// Creates a new instance of an [`Error`] from a particular OS error code. |
647 | /// |
648 | /// # Examples |
649 | /// |
650 | /// On Linux: |
651 | /// |
652 | /// ``` |
653 | /// # if cfg!(target_os = "linux" ) { |
654 | /// use std::io; |
655 | /// |
656 | /// let error = io::Error::from_raw_os_error(22); |
657 | /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput); |
658 | /// # } |
659 | /// ``` |
660 | /// |
661 | /// On Windows: |
662 | /// |
663 | /// ``` |
664 | /// # if cfg!(windows) { |
665 | /// use std::io; |
666 | /// |
667 | /// let error = io::Error::from_raw_os_error(10022); |
668 | /// assert_eq!(error.kind(), io::ErrorKind::InvalidInput); |
669 | /// # } |
670 | /// ``` |
671 | #[stable (feature = "rust1" , since = "1.0.0" )] |
672 | #[must_use ] |
673 | #[inline ] |
674 | pub fn from_raw_os_error(code: RawOsError) -> Error { |
675 | Error { repr: Repr::new_os(code) } |
676 | } |
677 | |
678 | /// Returns the OS error that this error represents (if any). |
679 | /// |
680 | /// If this [`Error`] was constructed via [`last_os_error`] or |
681 | /// [`from_raw_os_error`], then this function will return [`Some`], otherwise |
682 | /// it will return [`None`]. |
683 | /// |
684 | /// [`last_os_error`]: Error::last_os_error |
685 | /// [`from_raw_os_error`]: Error::from_raw_os_error |
686 | /// |
687 | /// # Examples |
688 | /// |
689 | /// ``` |
690 | /// use std::io::{Error, ErrorKind}; |
691 | /// |
692 | /// fn print_os_error(err: &Error) { |
693 | /// if let Some(raw_os_err) = err.raw_os_error() { |
694 | /// println!("raw OS error: {raw_os_err:?}" ); |
695 | /// } else { |
696 | /// println!("Not an OS error" ); |
697 | /// } |
698 | /// } |
699 | /// |
700 | /// fn main() { |
701 | /// // Will print "raw OS error: ...". |
702 | /// print_os_error(&Error::last_os_error()); |
703 | /// // Will print "Not an OS error". |
704 | /// print_os_error(&Error::new(ErrorKind::Other, "oh no!" )); |
705 | /// } |
706 | /// ``` |
707 | #[stable (feature = "rust1" , since = "1.0.0" )] |
708 | #[must_use ] |
709 | #[inline ] |
710 | pub fn raw_os_error(&self) -> Option<RawOsError> { |
711 | match self.repr.data() { |
712 | ErrorData::Os(i) => Some(i), |
713 | ErrorData::Custom(..) => None, |
714 | ErrorData::Simple(..) => None, |
715 | ErrorData::SimpleMessage(..) => None, |
716 | } |
717 | } |
718 | |
719 | /// Returns a reference to the inner error wrapped by this error (if any). |
720 | /// |
721 | /// If this [`Error`] was constructed via [`new`] then this function will |
722 | /// return [`Some`], otherwise it will return [`None`]. |
723 | /// |
724 | /// [`new`]: Error::new |
725 | /// |
726 | /// # Examples |
727 | /// |
728 | /// ``` |
729 | /// use std::io::{Error, ErrorKind}; |
730 | /// |
731 | /// fn print_error(err: &Error) { |
732 | /// if let Some(inner_err) = err.get_ref() { |
733 | /// println!("Inner error: {inner_err:?}" ); |
734 | /// } else { |
735 | /// println!("No inner error" ); |
736 | /// } |
737 | /// } |
738 | /// |
739 | /// fn main() { |
740 | /// // Will print "No inner error". |
741 | /// print_error(&Error::last_os_error()); |
742 | /// // Will print "Inner error: ...". |
743 | /// print_error(&Error::new(ErrorKind::Other, "oh no!" )); |
744 | /// } |
745 | /// ``` |
746 | #[stable (feature = "io_error_inner" , since = "1.3.0" )] |
747 | #[must_use ] |
748 | #[inline ] |
749 | pub fn get_ref(&self) -> Option<&(dyn error::Error + Send + Sync + 'static)> { |
750 | match self.repr.data() { |
751 | ErrorData::Os(..) => None, |
752 | ErrorData::Simple(..) => None, |
753 | ErrorData::SimpleMessage(..) => None, |
754 | ErrorData::Custom(c) => Some(&*c.error), |
755 | } |
756 | } |
757 | |
758 | /// Returns a mutable reference to the inner error wrapped by this error |
759 | /// (if any). |
760 | /// |
761 | /// If this [`Error`] was constructed via [`new`] then this function will |
762 | /// return [`Some`], otherwise it will return [`None`]. |
763 | /// |
764 | /// [`new`]: Error::new |
765 | /// |
766 | /// # Examples |
767 | /// |
768 | /// ``` |
769 | /// use std::io::{Error, ErrorKind}; |
770 | /// use std::{error, fmt}; |
771 | /// use std::fmt::Display; |
772 | /// |
773 | /// #[derive(Debug)] |
774 | /// struct MyError { |
775 | /// v: String, |
776 | /// } |
777 | /// |
778 | /// impl MyError { |
779 | /// fn new() -> MyError { |
780 | /// MyError { |
781 | /// v: "oh no!" .to_string() |
782 | /// } |
783 | /// } |
784 | /// |
785 | /// fn change_message(&mut self, new_message: &str) { |
786 | /// self.v = new_message.to_string(); |
787 | /// } |
788 | /// } |
789 | /// |
790 | /// impl error::Error for MyError {} |
791 | /// |
792 | /// impl Display for MyError { |
793 | /// fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
794 | /// write!(f, "MyError: {}" , self.v) |
795 | /// } |
796 | /// } |
797 | /// |
798 | /// fn change_error(mut err: Error) -> Error { |
799 | /// if let Some(inner_err) = err.get_mut() { |
800 | /// inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!" ); |
801 | /// } |
802 | /// err |
803 | /// } |
804 | /// |
805 | /// fn print_error(err: &Error) { |
806 | /// if let Some(inner_err) = err.get_ref() { |
807 | /// println!("Inner error: {inner_err}" ); |
808 | /// } else { |
809 | /// println!("No inner error" ); |
810 | /// } |
811 | /// } |
812 | /// |
813 | /// fn main() { |
814 | /// // Will print "No inner error". |
815 | /// print_error(&change_error(Error::last_os_error())); |
816 | /// // Will print "Inner error: ...". |
817 | /// print_error(&change_error(Error::new(ErrorKind::Other, MyError::new()))); |
818 | /// } |
819 | /// ``` |
820 | #[stable (feature = "io_error_inner" , since = "1.3.0" )] |
821 | #[must_use ] |
822 | #[inline ] |
823 | pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error + Send + Sync + 'static)> { |
824 | match self.repr.data_mut() { |
825 | ErrorData::Os(..) => None, |
826 | ErrorData::Simple(..) => None, |
827 | ErrorData::SimpleMessage(..) => None, |
828 | ErrorData::Custom(c) => Some(&mut *c.error), |
829 | } |
830 | } |
831 | |
832 | /// Consumes the `Error`, returning its inner error (if any). |
833 | /// |
834 | /// If this [`Error`] was constructed via [`new`] or [`other`], |
835 | /// then this function will return [`Some`], |
836 | /// otherwise it will return [`None`]. |
837 | /// |
838 | /// [`new`]: Error::new |
839 | /// [`other`]: Error::other |
840 | /// |
841 | /// # Examples |
842 | /// |
843 | /// ``` |
844 | /// use std::io::{Error, ErrorKind}; |
845 | /// |
846 | /// fn print_error(err: Error) { |
847 | /// if let Some(inner_err) = err.into_inner() { |
848 | /// println!("Inner error: {inner_err}" ); |
849 | /// } else { |
850 | /// println!("No inner error" ); |
851 | /// } |
852 | /// } |
853 | /// |
854 | /// fn main() { |
855 | /// // Will print "No inner error". |
856 | /// print_error(Error::last_os_error()); |
857 | /// // Will print "Inner error: ...". |
858 | /// print_error(Error::new(ErrorKind::Other, "oh no!" )); |
859 | /// } |
860 | /// ``` |
861 | #[stable (feature = "io_error_inner" , since = "1.3.0" )] |
862 | #[must_use = "`self` will be dropped if the result is not used" ] |
863 | #[inline ] |
864 | pub fn into_inner(self) -> Option<Box<dyn error::Error + Send + Sync>> { |
865 | match self.repr.into_data() { |
866 | ErrorData::Os(..) => None, |
867 | ErrorData::Simple(..) => None, |
868 | ErrorData::SimpleMessage(..) => None, |
869 | ErrorData::Custom(c) => Some(c.error), |
870 | } |
871 | } |
872 | |
873 | /// Attempts to downcast the custom boxed error to `E`. |
874 | /// |
875 | /// If this [`Error`] contains a custom boxed error, |
876 | /// then it would attempt downcasting on the boxed error, |
877 | /// otherwise it will return [`Err`]. |
878 | /// |
879 | /// If the custom boxed error has the same type as `E`, it will return [`Ok`], |
880 | /// otherwise it will also return [`Err`]. |
881 | /// |
882 | /// This method is meant to be a convenience routine for calling |
883 | /// `Box<dyn Error + Sync + Send>::downcast` on the custom boxed error, returned by |
884 | /// [`Error::into_inner`]. |
885 | /// |
886 | /// |
887 | /// # Examples |
888 | /// |
889 | /// ``` |
890 | /// use std::fmt; |
891 | /// use std::io; |
892 | /// use std::error::Error; |
893 | /// |
894 | /// #[derive(Debug)] |
895 | /// enum E { |
896 | /// Io(io::Error), |
897 | /// SomeOtherVariant, |
898 | /// } |
899 | /// |
900 | /// impl fmt::Display for E { |
901 | /// // ... |
902 | /// # fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
903 | /// # todo!() |
904 | /// # } |
905 | /// } |
906 | /// impl Error for E {} |
907 | /// |
908 | /// impl From<io::Error> for E { |
909 | /// fn from(err: io::Error) -> E { |
910 | /// err.downcast::<E>() |
911 | /// .unwrap_or_else(E::Io) |
912 | /// } |
913 | /// } |
914 | /// |
915 | /// impl From<E> for io::Error { |
916 | /// fn from(err: E) -> io::Error { |
917 | /// match err { |
918 | /// E::Io(io_error) => io_error, |
919 | /// e => io::Error::new(io::ErrorKind::Other, e), |
920 | /// } |
921 | /// } |
922 | /// } |
923 | /// |
924 | /// # fn main() { |
925 | /// let e = E::SomeOtherVariant; |
926 | /// // Convert it to an io::Error |
927 | /// let io_error = io::Error::from(e); |
928 | /// // Cast it back to the original variant |
929 | /// let e = E::from(io_error); |
930 | /// assert!(matches!(e, E::SomeOtherVariant)); |
931 | /// |
932 | /// let io_error = io::Error::from(io::ErrorKind::AlreadyExists); |
933 | /// // Convert it to E |
934 | /// let e = E::from(io_error); |
935 | /// // Cast it back to the original variant |
936 | /// let io_error = io::Error::from(e); |
937 | /// assert_eq!(io_error.kind(), io::ErrorKind::AlreadyExists); |
938 | /// assert!(io_error.get_ref().is_none()); |
939 | /// assert!(io_error.raw_os_error().is_none()); |
940 | /// # } |
941 | /// ``` |
942 | #[stable (feature = "io_error_downcast" , since = "1.79.0" )] |
943 | pub fn downcast<E>(self) -> result::Result<E, Self> |
944 | where |
945 | E: error::Error + Send + Sync + 'static, |
946 | { |
947 | match self.repr.into_data() { |
948 | ErrorData::Custom(b) if b.error.is::<E>() => { |
949 | let res = (*b).error.downcast::<E>(); |
950 | |
951 | // downcast is a really trivial and is marked as inline, so |
952 | // it's likely be inlined here. |
953 | // |
954 | // And the compiler should be able to eliminate the branch |
955 | // that produces `Err` here since b.error.is::<E>() |
956 | // returns true. |
957 | Ok(*res.unwrap()) |
958 | } |
959 | repr_data => Err(Self { repr: Repr::new(repr_data) }), |
960 | } |
961 | } |
962 | |
963 | /// Returns the corresponding [`ErrorKind`] for this error. |
964 | /// |
965 | /// This may be a value set by Rust code constructing custom `io::Error`s, |
966 | /// or if this `io::Error` was sourced from the operating system, |
967 | /// it will be a value inferred from the system's error encoding. |
968 | /// See [`last_os_error`] for more details. |
969 | /// |
970 | /// [`last_os_error`]: Error::last_os_error |
971 | /// |
972 | /// # Examples |
973 | /// |
974 | /// ``` |
975 | /// use std::io::{Error, ErrorKind}; |
976 | /// |
977 | /// fn print_error(err: Error) { |
978 | /// println!("{:?}" , err.kind()); |
979 | /// } |
980 | /// |
981 | /// fn main() { |
982 | /// // As no error has (visibly) occurred, this may print anything! |
983 | /// // It likely prints a placeholder for unidentified (non-)errors. |
984 | /// print_error(Error::last_os_error()); |
985 | /// // Will print "AddrInUse". |
986 | /// print_error(Error::new(ErrorKind::AddrInUse, "oh no!" )); |
987 | /// } |
988 | /// ``` |
989 | #[stable (feature = "rust1" , since = "1.0.0" )] |
990 | #[must_use ] |
991 | #[inline ] |
992 | pub fn kind(&self) -> ErrorKind { |
993 | match self.repr.data() { |
994 | ErrorData::Os(code) => sys::decode_error_kind(code), |
995 | ErrorData::Custom(c) => c.kind, |
996 | ErrorData::Simple(kind) => kind, |
997 | ErrorData::SimpleMessage(m) => m.kind, |
998 | } |
999 | } |
1000 | |
1001 | #[inline ] |
1002 | pub(crate) fn is_interrupted(&self) -> bool { |
1003 | match self.repr.data() { |
1004 | ErrorData::Os(code) => sys::is_interrupted(code), |
1005 | ErrorData::Custom(c) => c.kind == ErrorKind::Interrupted, |
1006 | ErrorData::Simple(kind) => kind == ErrorKind::Interrupted, |
1007 | ErrorData::SimpleMessage(m) => m.kind == ErrorKind::Interrupted, |
1008 | } |
1009 | } |
1010 | } |
1011 | |
1012 | impl fmt::Debug for Repr { |
1013 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
1014 | match self.data() { |
1015 | ErrorData::Os(code: i32) => fmt&mut DebugStruct<'_, '_> |
1016 | .debug_struct("Os" ) |
1017 | .field("code" , &code) |
1018 | .field("kind" , &sys::decode_error_kind(code)) |
1019 | .field(name:"message" , &sys::os::error_string(errno:code)) |
1020 | .finish(), |
1021 | ErrorData::Custom(c: &Custom) => fmt::Debug::fmt(&c, f:fmt), |
1022 | ErrorData::Simple(kind: ErrorKind) => fmt.debug_tuple(name:"Kind" ).field(&kind).finish(), |
1023 | ErrorData::SimpleMessage(msg: &'static SimpleMessage) => fmt&mut DebugStruct<'_, '_> |
1024 | .debug_struct("Error" ) |
1025 | .field("kind" , &msg.kind) |
1026 | .field(name:"message" , &msg.message) |
1027 | .finish(), |
1028 | } |
1029 | } |
1030 | } |
1031 | |
1032 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1033 | impl fmt::Display for Error { |
1034 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
1035 | match self.repr.data() { |
1036 | ErrorData::Os(code: i32) => { |
1037 | let detail: String = sys::os::error_string(errno:code); |
1038 | write!(fmt, " {detail} (os error {code})" ) |
1039 | } |
1040 | ErrorData::Custom(ref c: &&Custom) => c.error.fmt(fmt), |
1041 | ErrorData::Simple(kind: ErrorKind) => write!(fmt, " {}" , kind.as_str()), |
1042 | ErrorData::SimpleMessage(msg: &'static SimpleMessage) => msg.message.fmt(fmt), |
1043 | } |
1044 | } |
1045 | } |
1046 | |
1047 | #[stable (feature = "rust1" , since = "1.0.0" )] |
1048 | impl error::Error for Error { |
1049 | #[allow (deprecated, deprecated_in_future)] |
1050 | fn description(&self) -> &str { |
1051 | match self.repr.data() { |
1052 | ErrorData::Os(..) | ErrorData::Simple(..) => self.kind().as_str(), |
1053 | ErrorData::SimpleMessage(msg) => msg.message, |
1054 | ErrorData::Custom(c) => c.error.description(), |
1055 | } |
1056 | } |
1057 | |
1058 | #[allow (deprecated)] |
1059 | fn cause(&self) -> Option<&dyn error::Error> { |
1060 | match self.repr.data() { |
1061 | ErrorData::Os(..) => None, |
1062 | ErrorData::Simple(..) => None, |
1063 | ErrorData::SimpleMessage(..) => None, |
1064 | ErrorData::Custom(c) => c.error.cause(), |
1065 | } |
1066 | } |
1067 | |
1068 | fn source(&self) -> Option<&(dyn error::Error + 'static)> { |
1069 | match self.repr.data() { |
1070 | ErrorData::Os(..) => None, |
1071 | ErrorData::Simple(..) => None, |
1072 | ErrorData::SimpleMessage(..) => None, |
1073 | ErrorData::Custom(c) => c.error.source(), |
1074 | } |
1075 | } |
1076 | } |
1077 | |
1078 | fn _assert_error_is_sync_send() { |
1079 | fn _is_sync_send<T: Sync + Send>() {} |
1080 | _is_sync_send::<Error>(); |
1081 | } |
1082 | |