std/io/
error.rs

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

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy