123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- // 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.
- use boxed::Box;
- use convert::Into;
- use error;
- use fmt;
- use marker::{Send, Sync};
- use option::Option::{self, Some, None};
- use result;
- use sys;
- /// A specialized [`Result`](../result/enum.Result.html) type for I/O
- /// operations.
- ///
- /// This type is broadly used across `std::io` for any operation which may
- /// produce an error.
- ///
- /// This typedef is generally used to avoid writing out `io::Error` directly and
- /// is otherwise a direct mapping to `Result`.
- ///
- /// 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`, and so users of this alias
- /// will generally use `io::Result` instead of shadowing the prelude's import
- /// of `std::result::Result`.
- ///
- /// # 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();
- ///
- /// try!(io::stdin().read_line(&mut buffer));
- ///
- /// Ok(buffer)
- /// }
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub type Result<T> = result::Result<T, Error>;
- /// 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
- /// `ErrorKind`.
- #[derive(Debug)]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub struct Error {
- repr: Repr,
- }
- enum Repr {
- Os(i32),
- Custom(Box<Custom>),
- }
- #[derive(Debug)]
- struct Custom {
- kind: ErrorKind,
- error: Box<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.
- #[derive(Copy, PartialEq, Eq, Clone, Debug)]
- #[stable(feature = "rust1", since = "1.0.0")]
- #[allow(deprecated)]
- 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.
- #[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.
- #[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,
- /// 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,
- /// Any I/O error not part of this list.
- #[unstable(feature = "io_error_internals",
- reason = "better expressed through extensible enums that this \
- enum cannot be exhaustively matched against",
- issue = "0")]
- #[doc(hidden)]
- __Nonexhaustive,
- }
- 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<error::Error+Send+Sync>>
- {
- Self::_new(kind, error.into())
- }
- fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
- Error {
- repr: Repr::Custom(Box::new(Custom {
- kind: kind,
- error: 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.
- #[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(98);
- /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
- /// # }
- /// ```
- ///
- /// On Windows:
- ///
- /// ```
- /// # if cfg!(windows) {
- /// use std::io;
- ///
- /// let error = io::Error::from_raw_os_error(10048);
- /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
- /// # }
- /// ```
- #[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`.
- #[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,
- }
- }
- /// 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`.
- #[stable(feature = "io_error_inner", since = "1.3.0")]
- pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
- match self.repr {
- Repr::Os(..) => 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`.
- #[stable(feature = "io_error_inner", since = "1.3.0")]
- pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
- match self.repr {
- Repr::Os(..) => 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`.
- #[stable(feature = "io_error_inner", since = "1.3.0")]
- pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
- match self.repr {
- Repr::Os(..) => None,
- Repr::Custom(c) => Some(c.error)
- }
- }
- /// Returns the corresponding `ErrorKind` for this error.
- #[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,
- }
- }
- }
- impl fmt::Debug for Repr {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Repr::Os(ref code) =>
- fmt.debug_struct("Os").field("code", code)
- .field("message", &sys::os::error_string(*code)).finish(),
- Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
- }
- }
- }
- #[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),
- }
- }
- }
- #[stable(feature = "rust1", since = "1.0.0")]
- impl error::Error for Error {
- fn description(&self) -> &str {
- match self.repr {
- Repr::Os(..) => match self.kind() {
- 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",
- ErrorKind::__Nonexhaustive => unreachable!()
- },
- Repr::Custom(ref c) => c.error.description(),
- }
- }
- fn cause(&self) -> Option<&error::Error> {
- match self.repr {
- Repr::Os(..) => 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 {
- use prelude::v1::*;
- use super::{Error, ErrorKind};
- use error;
- use fmt;
- use sys::os::error_string;
- #[test]
- fn test_debug_error() {
- let code = 6;
- let msg = error_string(code);
- let err = Error { repr: super::Repr::Os(code) };
- let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, 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();
- }
- }
|