rust/src/libstd/io/error.rs

634 lines
20 KiB
Rust
Raw Normal View History

// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
std: Stabilize the `io` module The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
2015-03-11 16:16:46 -05:00
use error;
use fmt;
use result;
use sys;
use convert::From;
2015-10-14 02:22:14 -05:00
/// A specialized [`Result`](../result/enum.Result.html) type for I/O
/// operations.
///
2017-08-10 16:05:50 -05:00
/// This type is broadly used across [`std::io`] for any operation which may
/// produce an error.
///
2017-08-10 16:05:50 -05:00
/// This typedef is generally used to avoid writing out [`io::Error`] directly and
/// is otherwise a direct mapping to [`Result`].
///
2017-08-10 16:05:50 -05:00
/// While usual Rust style is to import types directly, aliases of [`Result`]
/// often are not, to make it easier to distinguish between them. [`Result`] is
/// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
/// will generally use `io::Result` instead of shadowing the prelude's import
2017-08-10 16:05:50 -05:00
/// of [`std::result::Result`][`Result`].
///
/// [`std::io`]: ../io/index.html
/// [`io::Error`]: ../io/struct.Error.html
/// [`Result`]: ../result/enum.Result.html
///
/// # Examples
///
/// A convenience function that bubbles an `io::Result` to its caller:
///
/// ```
/// use std::io;
///
/// fn get_string() -> io::Result<String> {
/// let mut buffer = String::new();
///
/// io::stdin().read_line(&mut buffer)?;
///
/// Ok(buffer)
/// }
/// ```
std: Stabilize the `io` module The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
2015-03-11 16:16:46 -05:00
#[stable(feature = "rust1", since = "1.0.0")]
pub type Result<T> = result::Result<T, Error>;
2017-08-10 16:14:49 -05:00
/// The error type for I/O operations of the [`Read`], [`Write`], [`Seek`], and
/// associated traits.
///
/// Errors mostly originate from the underlying OS, but custom instances of
/// `Error` can be created with crafted error messages and a particular value of
2016-07-30 06:37:52 -05:00
/// [`ErrorKind`].
///
2017-08-10 16:14:49 -05:00
/// [`Read`]: ../io/trait.Read.html
/// [`Write`]: ../io/trait.Write.html
/// [`Seek`]: ../io/trait.Seek.html
2016-07-30 06:37:52 -05:00
/// [`ErrorKind`]: enum.ErrorKind.html
std: Stabilize the `io` module The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
2015-03-11 16:16:46 -05:00
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Error {
repr: Repr,
}
2018-01-01 20:56:22 -06:00
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Debug::fmt(&self.repr, f)
}
}
enum Repr {
Os(i32),
Simple(ErrorKind),
Custom(Box<Custom>),
}
#[derive(Debug)]
struct Custom {
kind: ErrorKind,
error: Box<dyn error::Error+Send+Sync>,
}
/// A list specifying general categories of I/O error.
///
/// This list is intended to grow over time and it is not recommended to
/// exhaustively match against it.
2016-07-30 06:37:52 -05:00
///
/// It is used with the [`io::Error`] type.
///
/// [`io::Error`]: struct.Error.html
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "rust1", since = "1.0.0")]
std: Stabilize APIs for the 1.6 release This commit is the standard API stabilization commit for the 1.6 release cycle. The list of issues and APIs below have all been through their cycle-long FCP and the libs team decisions are listed below Stabilized APIs * `Read::read_exact` * `ErrorKind::UnexpectedEof` (renamed from `UnexpectedEOF`) * libcore -- this was a bit of a nuanced stabilization, the crate itself is now marked as `#[stable]` and the methods appearing via traits for primitives like `char` and `str` are now also marked as stable. Note that the extension traits themeselves are marked as unstable as they're imported via the prelude. The `try!` macro was also moved from the standard library into libcore to have the same interface. Otherwise the functions all have copied stability from the standard library now. * The `#![no_std]` attribute * `fs::DirBuilder` * `fs::DirBuilder::new` * `fs::DirBuilder::recursive` * `fs::DirBuilder::create` * `os::unix::fs::DirBuilderExt` * `os::unix::fs::DirBuilderExt::mode` * `vec::Drain` * `vec::Vec::drain` * `string::Drain` * `string::String::drain` * `vec_deque::Drain` * `vec_deque::VecDeque::drain` * `collections::hash_map::Drain` * `collections::hash_map::HashMap::drain` * `collections::hash_set::Drain` * `collections::hash_set::HashSet::drain` * `collections::binary_heap::Drain` * `collections::binary_heap::BinaryHeap::drain` * `Vec::extend_from_slice` (renamed from `push_all`) * `Mutex::get_mut` * `Mutex::into_inner` * `RwLock::get_mut` * `RwLock::into_inner` * `Iterator::min_by_key` (renamed from `min_by`) * `Iterator::max_by_key` (renamed from `max_by`) Deprecated APIs * `ErrorKind::UnexpectedEOF` (renamed to `UnexpectedEof`) * `OsString::from_bytes` * `OsStr::to_cstring` * `OsStr::to_bytes` * `fs::walk_dir` and `fs::WalkDir` * `path::Components::peek` * `slice::bytes::MutableByteVector` * `slice::bytes::copy_memory` * `Vec::push_all` (renamed to `extend_from_slice`) * `Duration::span` * `IpAddr` * `SocketAddr::ip` * `Read::tee` * `io::Tee` * `Write::broadcast` * `io::Broadcast` * `Iterator::min_by` (renamed to `min_by_key`) * `Iterator::max_by` (renamed to `max_by_key`) * `net::lookup_addr` New APIs (still unstable) * `<[T]>::sort_by_key` (added to mirror `min_by_key`) Closes #27585 Closes #27704 Closes #27707 Closes #27710 Closes #27711 Closes #27727 Closes #27740 Closes #27744 Closes #27799 Closes #27801 cc #27801 (doesn't close as `Chars` is still unstable) Closes #28968
2015-12-02 19:31:49 -06:00
#[allow(deprecated)]
2018-08-15 10:57:06 -05:00
#[non_exhaustive]
pub enum ErrorKind {
/// An entity was not found, often a file.
#[stable(feature = "rust1", since = "1.0.0")]
NotFound,
/// The operation lacked the necessary privileges to complete.
#[stable(feature = "rust1", since = "1.0.0")]
PermissionDenied,
/// The connection was refused by the remote server.
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionRefused,
/// The connection was reset by the remote server.
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionReset,
/// The connection was aborted (terminated) by the remote server.
#[stable(feature = "rust1", since = "1.0.0")]
ConnectionAborted,
/// The network operation failed because it was not connected yet.
#[stable(feature = "rust1", since = "1.0.0")]
NotConnected,
/// A socket address could not be bound because the address is already in
/// use elsewhere.
#[stable(feature = "rust1", since = "1.0.0")]
AddrInUse,
/// A nonexistent interface was requested or the requested address was not
/// local.
#[stable(feature = "rust1", since = "1.0.0")]
AddrNotAvailable,
/// The operation failed because a pipe was closed.
#[stable(feature = "rust1", since = "1.0.0")]
BrokenPipe,
/// An entity already exists, often a file.
#[stable(feature = "rust1", since = "1.0.0")]
AlreadyExists,
/// The operation needs to block to complete, but the blocking operation was
/// requested to not occur.
#[stable(feature = "rust1", since = "1.0.0")]
WouldBlock,
/// A parameter was incorrect.
#[stable(feature = "rust1", since = "1.0.0")]
InvalidInput,
/// Data not valid for the operation were encountered.
///
/// Unlike [`InvalidInput`], this typically means that the operation
/// parameters were valid, however the error was caused by malformed
/// input data.
///
/// For example, a function that reads a file into a string will error with
/// `InvalidData` if the file's contents are not valid UTF-8.
///
/// [`InvalidInput`]: #variant.InvalidInput
#[stable(feature = "io_invalid_data", since = "1.2.0")]
InvalidData,
/// The I/O operation's timeout expired, causing it to be canceled.
#[stable(feature = "rust1", since = "1.0.0")]
TimedOut,
/// An error returned when an operation could not be completed because a
/// call to [`write`] returned [`Ok(0)`].
///
/// This typically means that an operation could only succeed if it wrote a
/// particular number of bytes but only a smaller number of bytes could be
/// written.
///
/// [`write`]: ../../std/io/trait.Write.html#tymethod.write
/// [`Ok(0)`]: ../../std/io/type.Result.html
#[stable(feature = "rust1", since = "1.0.0")]
WriteZero,
/// This operation was interrupted.
///
/// Interrupted operations can typically be retried.
#[stable(feature = "rust1", since = "1.0.0")]
Interrupted,
/// Any I/O error not part of this list.
#[stable(feature = "rust1", since = "1.0.0")]
Other,
std: Stabilize APIs for the 1.6 release This commit is the standard API stabilization commit for the 1.6 release cycle. The list of issues and APIs below have all been through their cycle-long FCP and the libs team decisions are listed below Stabilized APIs * `Read::read_exact` * `ErrorKind::UnexpectedEof` (renamed from `UnexpectedEOF`) * libcore -- this was a bit of a nuanced stabilization, the crate itself is now marked as `#[stable]` and the methods appearing via traits for primitives like `char` and `str` are now also marked as stable. Note that the extension traits themeselves are marked as unstable as they're imported via the prelude. The `try!` macro was also moved from the standard library into libcore to have the same interface. Otherwise the functions all have copied stability from the standard library now. * The `#![no_std]` attribute * `fs::DirBuilder` * `fs::DirBuilder::new` * `fs::DirBuilder::recursive` * `fs::DirBuilder::create` * `os::unix::fs::DirBuilderExt` * `os::unix::fs::DirBuilderExt::mode` * `vec::Drain` * `vec::Vec::drain` * `string::Drain` * `string::String::drain` * `vec_deque::Drain` * `vec_deque::VecDeque::drain` * `collections::hash_map::Drain` * `collections::hash_map::HashMap::drain` * `collections::hash_set::Drain` * `collections::hash_set::HashSet::drain` * `collections::binary_heap::Drain` * `collections::binary_heap::BinaryHeap::drain` * `Vec::extend_from_slice` (renamed from `push_all`) * `Mutex::get_mut` * `Mutex::into_inner` * `RwLock::get_mut` * `RwLock::into_inner` * `Iterator::min_by_key` (renamed from `min_by`) * `Iterator::max_by_key` (renamed from `max_by`) Deprecated APIs * `ErrorKind::UnexpectedEOF` (renamed to `UnexpectedEof`) * `OsString::from_bytes` * `OsStr::to_cstring` * `OsStr::to_bytes` * `fs::walk_dir` and `fs::WalkDir` * `path::Components::peek` * `slice::bytes::MutableByteVector` * `slice::bytes::copy_memory` * `Vec::push_all` (renamed to `extend_from_slice`) * `Duration::span` * `IpAddr` * `SocketAddr::ip` * `Read::tee` * `io::Tee` * `Write::broadcast` * `io::Broadcast` * `Iterator::min_by` (renamed to `min_by_key`) * `Iterator::max_by` (renamed to `max_by_key`) * `net::lookup_addr` New APIs (still unstable) * `<[T]>::sort_by_key` (added to mirror `min_by_key`) Closes #27585 Closes #27704 Closes #27707 Closes #27710 Closes #27711 Closes #27727 Closes #27740 Closes #27744 Closes #27799 Closes #27801 cc #27801 (doesn't close as `Chars` is still unstable) Closes #28968
2015-12-02 19:31:49 -06:00
/// An error returned when an operation could not be completed because an
/// "end of file" was reached prematurely.
///
/// This typically means that an operation could only succeed if it read a
/// particular number of bytes but only a smaller number of bytes could be
/// read.
#[stable(feature = "read_exact", since = "1.6.0")]
UnexpectedEof,
}
impl ErrorKind {
fn as_str(&self) -> &'static str {
match *self {
ErrorKind::NotFound => "entity not found",
ErrorKind::PermissionDenied => "permission denied",
ErrorKind::ConnectionRefused => "connection refused",
ErrorKind::ConnectionReset => "connection reset",
ErrorKind::ConnectionAborted => "connection aborted",
ErrorKind::NotConnected => "not connected",
ErrorKind::AddrInUse => "address in use",
ErrorKind::AddrNotAvailable => "address not available",
ErrorKind::BrokenPipe => "broken pipe",
ErrorKind::AlreadyExists => "entity already exists",
ErrorKind::WouldBlock => "operation would block",
ErrorKind::InvalidInput => "invalid input parameter",
ErrorKind::InvalidData => "invalid data",
ErrorKind::TimedOut => "timed out",
ErrorKind::WriteZero => "write zero",
ErrorKind::Interrupted => "operation interrupted",
ErrorKind::Other => "other os error",
ErrorKind::UnexpectedEof => "unexpected end of file",
}
}
}
/// Intended for use for errors not exposed to the user, where allocating onto
/// the heap (for normal construction via Error::new) is too costly.
#[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
impl From<ErrorKind> for Error {
2018-08-19 21:04:08 -05:00
/// Converts a [`ErrorKind`] into a [`Error`].
///
2018-09-26 14:34:12 -05:00
/// This conversion allocates a new error with a simple representation of error kind.
2018-08-19 21:04:08 -05:00
///
2018-09-26 14:34:12 -05:00
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
2018-10-02 17:25:31 -05:00
/// let not_found = ErrorKind::NotFound;
/// let error = Error::from(not_found);
/// assert_eq!("entity not found", format!("{}", error));
2018-09-26 14:34:12 -05:00
/// ```
#[inline]
fn from(kind: ErrorKind) -> Error {
Error {
repr: Repr::Simple(kind)
}
}
}
impl Error {
/// Creates a new I/O error from a known kind of error as well as an
/// arbitrary error payload.
///
/// This function is used to generically create I/O errors which do not
/// originate from the OS itself. The `error` argument is an arbitrary
/// payload which will be contained in this `Error`.
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// // errors can be created from strings
/// let custom_error = Error::new(ErrorKind::Other, "oh no!");
///
/// // errors can also be created from other errors
/// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<E>(kind: ErrorKind, error: E) -> Error
where E: Into<Box<dyn error::Error+Send+Sync>>
{
Self::_new(kind, error.into())
}
fn _new(kind: ErrorKind, error: Box<dyn error::Error+Send+Sync>) -> Error {
Error {
repr: Repr::Custom(Box::new(Custom {
kind,
error,
}))
}
}
/// Returns an error representing the last OS error which occurred.
///
/// This function reads the value of `errno` for the target platform (e.g.
/// `GetLastError` on Windows) and will return a corresponding instance of
/// `Error` for the error code.
2016-07-29 07:32:35 -05:00
///
/// # Examples
///
/// ```
/// use std::io::Error;
///
/// println!("last OS error: {:?}", Error::last_os_error());
/// ```
std: Stabilize the `io` module The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
2015-03-11 16:16:46 -05:00
#[stable(feature = "rust1", since = "1.0.0")]
pub fn last_os_error() -> Error {
Error::from_raw_os_error(sys::os::errno() as i32)
}
/// Creates a new instance of an `Error` from a particular OS error code.
///
/// # Examples
///
/// On Linux:
///
/// ```
/// # if cfg!(target_os = "linux") {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(22);
/// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
/// # }
/// ```
///
/// On Windows:
///
/// ```
/// # if cfg!(windows) {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(10022);
/// assert_eq!(error.kind(), io::ErrorKind::InvalidInput);
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_raw_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) }
}
/// Returns the OS error that this error represents (if any).
///
/// If this `Error` was constructed via `last_os_error` or
/// `from_raw_os_error`, then this function will return `Some`, otherwise
/// it will return `None`.
2016-07-29 07:32:35 -05:00
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_os_error(err: &Error) {
/// if let Some(raw_os_err) = err.raw_os_error() {
/// println!("raw OS error: {:?}", raw_os_err);
/// } else {
/// println!("Not an OS error");
/// }
/// }
///
/// fn main() {
/// // Will print "raw OS error: ...".
/// print_os_error(&Error::last_os_error());
/// // Will print "Not an OS error".
/// print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn raw_os_error(&self) -> Option<i32> {
match self.repr {
Repr::Os(i) => Some(i),
Repr::Custom(..) => None,
Repr::Simple(..) => None,
}
}
/// Returns a reference to the inner error wrapped by this error (if any).
///
/// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`.
2016-07-29 07:32:35 -05:00
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: &Error) {
/// if let Some(inner_err) = err.get_ref() {
/// println!("Inner error: {:?}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(&Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(&Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_ref(&self) -> Option<&(dyn error::Error+Send+Sync+'static)> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(ref c) => Some(&*c.error),
}
}
/// Returns a mutable reference to the inner error wrapped by this error
/// (if any).
///
/// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`.
2016-07-29 07:32:35 -05:00
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
/// use std::{error, fmt};
/// use std::fmt::Display;
///
/// #[derive(Debug)]
/// struct MyError {
/// v: String,
/// }
///
/// impl MyError {
/// fn new() -> MyError {
/// MyError {
/// v: "oh no!".to_string()
2016-07-29 07:32:35 -05:00
/// }
/// }
///
/// fn change_message(&mut self, new_message: &str) {
/// self.v = new_message.to_string();
2016-07-29 07:32:35 -05:00
/// }
/// }
///
/// impl error::Error for MyError {
/// fn description(&self) -> &str { &self.v }
/// }
///
/// impl Display for MyError {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// write!(f, "MyError: {}", &self.v)
/// }
/// }
///
/// fn change_error(mut err: Error) -> Error {
/// if let Some(inner_err) = err.get_mut() {
/// inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!");
/// }
/// err
/// }
///
/// fn print_error(err: &Error) {
/// if let Some(inner_err) = err.get_ref() {
/// println!("Inner error: {}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(&change_error(Error::last_os_error()));
/// // Will print "Inner error: ...".
/// print_error(&change_error(Error::new(ErrorKind::Other, MyError::new())));
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn get_mut(&mut self) -> Option<&mut (dyn error::Error+Send+Sync+'static)> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(ref mut c) => Some(&mut *c.error),
}
}
/// Consumes the `Error`, returning its inner error (if any).
///
/// If this `Error` was constructed via `new` then this function will
/// return `Some`, otherwise it will return `None`.
2016-07-29 07:32:35 -05:00
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: Error) {
/// if let Some(inner_err) = err.into_inner() {
/// println!("Inner error: {}", inner_err);
/// } else {
/// println!("No inner error");
/// }
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(Error::new(ErrorKind::Other, "oh no!"));
/// }
/// ```
#[stable(feature = "io_error_inner", since = "1.3.0")]
pub fn into_inner(self) -> Option<Box<dyn error::Error+Send+Sync>> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(c) => Some(c.error)
}
}
/// Returns the corresponding `ErrorKind` for this error.
2016-07-29 07:32:35 -05:00
///
/// # Examples
///
/// ```
/// use std::io::{Error, ErrorKind};
///
/// fn print_error(err: Error) {
/// println!("{:?}", err.kind());
/// }
///
/// fn main() {
/// // Will print "No inner error".
/// print_error(Error::last_os_error());
/// // Will print "Inner error: ...".
/// print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
/// }
/// ```
std: Stabilize the `io` module The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
2015-03-11 16:16:46 -05:00
#[stable(feature = "rust1", since = "1.0.0")]
pub fn kind(&self) -> ErrorKind {
match self.repr {
Repr::Os(code) => sys::decode_error_kind(code),
Repr::Custom(ref c) => c.kind,
Repr::Simple(kind) => kind,
}
}
}
impl fmt::Debug for Repr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
2015-09-07 17:36:29 -05:00
match *self {
2018-01-01 20:56:22 -06:00
Repr::Os(code) =>
fmt.debug_struct("Os")
.field("code", &code)
.field("kind", &sys::decode_error_kind(code))
.field("message", &sys::os::error_string(code)).finish(),
Repr::Custom(ref c) => fmt::Debug::fmt(&c, fmt),
Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
}
}
}
std: Stabilize the `io` module The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
2015-03-11 16:16:46 -05:00
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self.repr {
Repr::Os(code) => {
let detail = sys::os::error_string(code);
write!(fmt, "{} (os error {})", detail, code)
}
Repr::Custom(ref c) => c.error.fmt(fmt),
Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
}
}
}
std: Stabilize the `io` module The new `std::io` module has had some time to bake now, and this commit stabilizes its functionality. There are still portions of the module which remain unstable, and below contains a summart of the actions taken. This commit also deprecates the entire contents of the `old_io` module in a blanket fashion. All APIs should now have a reasonable replacement in the new I/O modules. Stable APIs: * `std::io` (the name) * `std::io::prelude` (the name) * `Read` * `Read::read` * `Read::{read_to_end, read_to_string}` after being modified to return a `usize` for the number of bytes read. * `Write` * `Write::write` * `Write::{write_all, write_fmt}` * `BufRead` * `BufRead::{fill_buf, consume}` * `BufRead::{read_line, read_until}` after being modified to return a `usize` for the number of bytes read. * `BufReader` * `BufReader::{new, with_capacity}` * `BufReader::{get_ref, get_mut, into_inner}` * `{Read,BufRead} for BufReader` * `BufWriter` * `BufWriter::{new, with_capacity}` * `BufWriter::{get_ref, get_mut, into_inner}` * `Write for BufWriter` * `IntoInnerError` * `IntoInnerError::{error, into_inner}` * `{Error,Display} for IntoInnerError` * `LineWriter` * `LineWriter::{new, with_capacity}` - `with_capacity` was added * `LineWriter::{get_ref, get_mut, into_inner}` - `get_mut` was added) * `Write for LineWriter` * `BufStream` * `BufStream::{new, with_capacities}` * `BufStream::{get_ref, get_mut, into_inner}` * `{BufRead,Read,Write} for BufStream` * `stdin` * `Stdin` * `Stdin::lock` * `Stdin::read_line` - added method * `StdinLock` * `Read for Stdin` * `{Read,BufRead} for StdinLock` * `stdout` * `Stdout` * `Stdout::lock` * `StdoutLock` * `Write for Stdout` * `Write for StdoutLock` * `stderr` * `Stderr` * `Stderr::lock` * `StderrLock` * `Write for Stderr` * `Write for StderrLock` * `io::Result` * `io::Error` * `io::Error::last_os_error` * `{Display, Error} for Error` Unstable APIs: (reasons can be found in the commit itself) * `Write::flush` * `Seek` * `ErrorKind` * `Error::new` * `Error::from_os_error` * `Error::kind` Deprecated APIs * `Error::description` - available via the `Error` trait * `Error::detail` - available via the `Display` implementation * `thread::Builder::{stdout, stderr}` Changes in functionality: * `old_io::stdio::set_stderr` is now a noop as the infrastructure for printing backtraces has migrated to `std::io`. * The `ReadExt`, `WriteExt`, and `BufReadExt` extension traits were all removed by folding functionality into the corresponding trait. [breaking-change]
2015-03-11 16:16:46 -05:00
#[stable(feature = "rust1", since = "1.0.0")]
impl error::Error for Error {
fn description(&self) -> &str {
match self.repr {
Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(),
Repr::Custom(ref c) => c.error.description(),
}
}
fn cause(&self) -> Option<&dyn error::Error> {
match self.repr {
Repr::Os(..) => None,
Repr::Simple(..) => None,
Repr::Custom(ref c) => c.error.cause(),
}
}
}
fn _assert_error_is_sync_send() {
fn _is_sync_send<T: Sync+Send>() {}
_is_sync_send::<Error>();
}
#[cfg(test)]
mod test {
2018-01-01 20:56:22 -06:00
use super::{Error, ErrorKind, Repr, Custom};
use error;
use fmt;
use sys::os::error_string;
2018-01-01 20:56:22 -06:00
use sys::decode_error_kind;
#[test]
fn test_debug_error() {
let code = 6;
let msg = error_string(code);
2018-01-01 20:56:22 -06:00
let kind = decode_error_kind(code);
let err = Error {
repr: Repr::Custom(box Custom {
kind: ErrorKind::InvalidInput,
error: box Error {
repr: super::Repr::Os(code)
},
})
};
let expected = format!(
"Custom {{ \
kind: InvalidInput, \
error: Os {{ \
code: {:?}, \
kind: {:?}, \
message: {:?} \
}} \
}}",
code, kind, msg
);
assert_eq!(format!("{:?}", err), expected);
}
#[test]
fn test_downcasting() {
#[derive(Debug)]
struct TestError;
impl fmt::Display for TestError {
fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
Ok(())
}
}
impl error::Error for TestError {
fn description(&self) -> &str {
"asdf"
}
}
// we have to call all of these UFCS style right now since method
// resolution won't implicitly drop the Send+Sync bounds
let mut err = Error::new(ErrorKind::Other, TestError);
assert!(err.get_ref().unwrap().is::<TestError>());
assert_eq!("asdf", err.get_ref().unwrap().description());
assert!(err.get_mut().unwrap().is::<TestError>());
let extracted = err.into_inner().unwrap();
extracted.downcast::<TestError>().unwrap();
}
}