error.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
  2. // file at the top-level directory of this distribution and at
  3. // http://rust-lang.org/COPYRIGHT.
  4. //
  5. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8. // option. This file may not be copied, modified, or distributed
  9. // except according to those terms.
  10. use boxed::Box;
  11. use convert::Into;
  12. use error;
  13. use fmt;
  14. use marker::{Send, Sync};
  15. use option::Option::{self, Some, None};
  16. use result;
  17. use sys;
  18. /// A specialized [`Result`](../result/enum.Result.html) type for I/O
  19. /// operations.
  20. ///
  21. /// This type is broadly used across `std::io` for any operation which may
  22. /// produce an error.
  23. ///
  24. /// This typedef is generally used to avoid writing out `io::Error` directly and
  25. /// is otherwise a direct mapping to `Result`.
  26. ///
  27. /// While usual Rust style is to import types directly, aliases of `Result`
  28. /// often are not, to make it easier to distinguish between them. `Result` is
  29. /// generally assumed to be `std::result::Result`, and so users of this alias
  30. /// will generally use `io::Result` instead of shadowing the prelude's import
  31. /// of `std::result::Result`.
  32. ///
  33. /// # Examples
  34. ///
  35. /// A convenience function that bubbles an `io::Result` to its caller:
  36. ///
  37. /// ```
  38. /// use std::io;
  39. ///
  40. /// fn get_string() -> io::Result<String> {
  41. /// let mut buffer = String::new();
  42. ///
  43. /// try!(io::stdin().read_line(&mut buffer));
  44. ///
  45. /// Ok(buffer)
  46. /// }
  47. /// ```
  48. #[stable(feature = "rust1", since = "1.0.0")]
  49. pub type Result<T> = result::Result<T, Error>;
  50. /// The error type for I/O operations of the `Read`, `Write`, `Seek`, and
  51. /// associated traits.
  52. ///
  53. /// Errors mostly originate from the underlying OS, but custom instances of
  54. /// `Error` can be created with crafted error messages and a particular value of
  55. /// `ErrorKind`.
  56. #[derive(Debug)]
  57. #[stable(feature = "rust1", since = "1.0.0")]
  58. pub struct Error {
  59. repr: Repr,
  60. }
  61. enum Repr {
  62. Os(i32),
  63. Custom(Box<Custom>),
  64. }
  65. #[derive(Debug)]
  66. struct Custom {
  67. kind: ErrorKind,
  68. error: Box<error::Error+Send+Sync>,
  69. }
  70. /// A list specifying general categories of I/O error.
  71. ///
  72. /// This list is intended to grow over time and it is not recommended to
  73. /// exhaustively match against it.
  74. #[derive(Copy, PartialEq, Eq, Clone, Debug)]
  75. #[stable(feature = "rust1", since = "1.0.0")]
  76. #[allow(deprecated)]
  77. pub enum ErrorKind {
  78. /// An entity was not found, often a file.
  79. #[stable(feature = "rust1", since = "1.0.0")]
  80. NotFound,
  81. /// The operation lacked the necessary privileges to complete.
  82. #[stable(feature = "rust1", since = "1.0.0")]
  83. PermissionDenied,
  84. /// The connection was refused by the remote server.
  85. #[stable(feature = "rust1", since = "1.0.0")]
  86. ConnectionRefused,
  87. /// The connection was reset by the remote server.
  88. #[stable(feature = "rust1", since = "1.0.0")]
  89. ConnectionReset,
  90. /// The connection was aborted (terminated) by the remote server.
  91. #[stable(feature = "rust1", since = "1.0.0")]
  92. ConnectionAborted,
  93. /// The network operation failed because it was not connected yet.
  94. #[stable(feature = "rust1", since = "1.0.0")]
  95. NotConnected,
  96. /// A socket address could not be bound because the address is already in
  97. /// use elsewhere.
  98. #[stable(feature = "rust1", since = "1.0.0")]
  99. AddrInUse,
  100. /// A nonexistent interface was requested or the requested address was not
  101. /// local.
  102. #[stable(feature = "rust1", since = "1.0.0")]
  103. AddrNotAvailable,
  104. /// The operation failed because a pipe was closed.
  105. #[stable(feature = "rust1", since = "1.0.0")]
  106. BrokenPipe,
  107. /// An entity already exists, often a file.
  108. #[stable(feature = "rust1", since = "1.0.0")]
  109. AlreadyExists,
  110. /// The operation needs to block to complete, but the blocking operation was
  111. /// requested to not occur.
  112. #[stable(feature = "rust1", since = "1.0.0")]
  113. WouldBlock,
  114. /// A parameter was incorrect.
  115. #[stable(feature = "rust1", since = "1.0.0")]
  116. InvalidInput,
  117. /// Data not valid for the operation were encountered.
  118. ///
  119. /// Unlike `InvalidInput`, this typically means that the operation
  120. /// parameters were valid, however the error was caused by malformed
  121. /// input data.
  122. ///
  123. /// For example, a function that reads a file into a string will error with
  124. /// `InvalidData` if the file's contents are not valid UTF-8.
  125. #[stable(feature = "io_invalid_data", since = "1.2.0")]
  126. InvalidData,
  127. /// The I/O operation's timeout expired, causing it to be canceled.
  128. #[stable(feature = "rust1", since = "1.0.0")]
  129. TimedOut,
  130. /// An error returned when an operation could not be completed because a
  131. /// call to `write` returned `Ok(0)`.
  132. ///
  133. /// This typically means that an operation could only succeed if it wrote a
  134. /// particular number of bytes but only a smaller number of bytes could be
  135. /// written.
  136. #[stable(feature = "rust1", since = "1.0.0")]
  137. WriteZero,
  138. /// This operation was interrupted.
  139. ///
  140. /// Interrupted operations can typically be retried.
  141. #[stable(feature = "rust1", since = "1.0.0")]
  142. Interrupted,
  143. /// Any I/O error not part of this list.
  144. #[stable(feature = "rust1", since = "1.0.0")]
  145. Other,
  146. /// An error returned when an operation could not be completed because an
  147. /// "end of file" was reached prematurely.
  148. ///
  149. /// This typically means that an operation could only succeed if it read a
  150. /// particular number of bytes but only a smaller number of bytes could be
  151. /// read.
  152. #[stable(feature = "read_exact", since = "1.6.0")]
  153. UnexpectedEof,
  154. /// Any I/O error not part of this list.
  155. #[unstable(feature = "io_error_internals",
  156. reason = "better expressed through extensible enums that this \
  157. enum cannot be exhaustively matched against",
  158. issue = "0")]
  159. #[doc(hidden)]
  160. __Nonexhaustive,
  161. }
  162. impl Error {
  163. /// Creates a new I/O error from a known kind of error as well as an
  164. /// arbitrary error payload.
  165. ///
  166. /// This function is used to generically create I/O errors which do not
  167. /// originate from the OS itself. The `error` argument is an arbitrary
  168. /// payload which will be contained in this `Error`.
  169. ///
  170. /// # Examples
  171. ///
  172. /// ```
  173. /// use std::io::{Error, ErrorKind};
  174. ///
  175. /// // errors can be created from strings
  176. /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
  177. ///
  178. /// // errors can also be created from other errors
  179. /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
  180. /// ```
  181. #[stable(feature = "rust1", since = "1.0.0")]
  182. pub fn new<E>(kind: ErrorKind, error: E) -> Error
  183. where E: Into<Box<error::Error+Send+Sync>>
  184. {
  185. Self::_new(kind, error.into())
  186. }
  187. fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
  188. Error {
  189. repr: Repr::Custom(Box::new(Custom {
  190. kind: kind,
  191. error: error,
  192. }))
  193. }
  194. }
  195. /// Returns an error representing the last OS error which occurred.
  196. ///
  197. /// This function reads the value of `errno` for the target platform (e.g.
  198. /// `GetLastError` on Windows) and will return a corresponding instance of
  199. /// `Error` for the error code.
  200. #[stable(feature = "rust1", since = "1.0.0")]
  201. pub fn last_os_error() -> Error {
  202. Error::from_raw_os_error(sys::os::errno() as i32)
  203. }
  204. /// Creates a new instance of an `Error` from a particular OS error code.
  205. ///
  206. /// # Examples
  207. ///
  208. /// On Linux:
  209. ///
  210. /// ```
  211. /// # if cfg!(target_os = "linux") {
  212. /// use std::io;
  213. ///
  214. /// let error = io::Error::from_raw_os_error(98);
  215. /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
  216. /// # }
  217. /// ```
  218. ///
  219. /// On Windows:
  220. ///
  221. /// ```
  222. /// # if cfg!(windows) {
  223. /// use std::io;
  224. ///
  225. /// let error = io::Error::from_raw_os_error(10048);
  226. /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
  227. /// # }
  228. /// ```
  229. #[stable(feature = "rust1", since = "1.0.0")]
  230. pub fn from_raw_os_error(code: i32) -> Error {
  231. Error { repr: Repr::Os(code) }
  232. }
  233. /// Returns the OS error that this error represents (if any).
  234. ///
  235. /// If this `Error` was constructed via `last_os_error` or
  236. /// `from_raw_os_error`, then this function will return `Some`, otherwise
  237. /// it will return `None`.
  238. #[stable(feature = "rust1", since = "1.0.0")]
  239. pub fn raw_os_error(&self) -> Option<i32> {
  240. match self.repr {
  241. Repr::Os(i) => Some(i),
  242. Repr::Custom(..) => None,
  243. }
  244. }
  245. /// Returns a reference to the inner error wrapped by this error (if any).
  246. ///
  247. /// If this `Error` was constructed via `new` then this function will
  248. /// return `Some`, otherwise it will return `None`.
  249. #[stable(feature = "io_error_inner", since = "1.3.0")]
  250. pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
  251. match self.repr {
  252. Repr::Os(..) => None,
  253. Repr::Custom(ref c) => Some(&*c.error),
  254. }
  255. }
  256. /// Returns a mutable reference to the inner error wrapped by this error
  257. /// (if any).
  258. ///
  259. /// If this `Error` was constructed via `new` then this function will
  260. /// return `Some`, otherwise it will return `None`.
  261. #[stable(feature = "io_error_inner", since = "1.3.0")]
  262. pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
  263. match self.repr {
  264. Repr::Os(..) => None,
  265. Repr::Custom(ref mut c) => Some(&mut *c.error),
  266. }
  267. }
  268. /// Consumes the `Error`, returning its inner error (if any).
  269. ///
  270. /// If this `Error` was constructed via `new` then this function will
  271. /// return `Some`, otherwise it will return `None`.
  272. #[stable(feature = "io_error_inner", since = "1.3.0")]
  273. pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
  274. match self.repr {
  275. Repr::Os(..) => None,
  276. Repr::Custom(c) => Some(c.error)
  277. }
  278. }
  279. /// Returns the corresponding `ErrorKind` for this error.
  280. #[stable(feature = "rust1", since = "1.0.0")]
  281. pub fn kind(&self) -> ErrorKind {
  282. match self.repr {
  283. Repr::Os(code) => sys::decode_error_kind(code),
  284. Repr::Custom(ref c) => c.kind,
  285. }
  286. }
  287. }
  288. impl fmt::Debug for Repr {
  289. fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
  290. match *self {
  291. Repr::Os(ref code) =>
  292. fmt.debug_struct("Os").field("code", code)
  293. .field("message", &sys::os::error_string(*code)).finish(),
  294. Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
  295. }
  296. }
  297. }
  298. #[stable(feature = "rust1", since = "1.0.0")]
  299. impl fmt::Display for Error {
  300. fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
  301. match self.repr {
  302. Repr::Os(code) => {
  303. let detail = sys::os::error_string(code);
  304. write!(fmt, "{} (os error {})", detail, code)
  305. }
  306. Repr::Custom(ref c) => c.error.fmt(fmt),
  307. }
  308. }
  309. }
  310. #[stable(feature = "rust1", since = "1.0.0")]
  311. impl error::Error for Error {
  312. fn description(&self) -> &str {
  313. match self.repr {
  314. Repr::Os(..) => match self.kind() {
  315. ErrorKind::NotFound => "entity not found",
  316. ErrorKind::PermissionDenied => "permission denied",
  317. ErrorKind::ConnectionRefused => "connection refused",
  318. ErrorKind::ConnectionReset => "connection reset",
  319. ErrorKind::ConnectionAborted => "connection aborted",
  320. ErrorKind::NotConnected => "not connected",
  321. ErrorKind::AddrInUse => "address in use",
  322. ErrorKind::AddrNotAvailable => "address not available",
  323. ErrorKind::BrokenPipe => "broken pipe",
  324. ErrorKind::AlreadyExists => "entity already exists",
  325. ErrorKind::WouldBlock => "operation would block",
  326. ErrorKind::InvalidInput => "invalid input parameter",
  327. ErrorKind::InvalidData => "invalid data",
  328. ErrorKind::TimedOut => "timed out",
  329. ErrorKind::WriteZero => "write zero",
  330. ErrorKind::Interrupted => "operation interrupted",
  331. ErrorKind::Other => "other os error",
  332. ErrorKind::UnexpectedEof => "unexpected end of file",
  333. ErrorKind::__Nonexhaustive => unreachable!()
  334. },
  335. Repr::Custom(ref c) => c.error.description(),
  336. }
  337. }
  338. fn cause(&self) -> Option<&error::Error> {
  339. match self.repr {
  340. Repr::Os(..) => None,
  341. Repr::Custom(ref c) => c.error.cause(),
  342. }
  343. }
  344. }
  345. fn _assert_error_is_sync_send() {
  346. fn _is_sync_send<T: Sync+Send>() {}
  347. _is_sync_send::<Error>();
  348. }
  349. #[cfg(test)]
  350. mod test {
  351. use prelude::v1::*;
  352. use super::{Error, ErrorKind};
  353. use error;
  354. use fmt;
  355. use sys::os::error_string;
  356. #[test]
  357. fn test_debug_error() {
  358. let code = 6;
  359. let msg = error_string(code);
  360. let err = Error { repr: super::Repr::Os(code) };
  361. let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
  362. assert_eq!(format!("{:?}", err), expected);
  363. }
  364. #[test]
  365. fn test_downcasting() {
  366. #[derive(Debug)]
  367. struct TestError;
  368. impl fmt::Display for TestError {
  369. fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
  370. Ok(())
  371. }
  372. }
  373. impl error::Error for TestError {
  374. fn description(&self) -> &str {
  375. "asdf"
  376. }
  377. }
  378. // we have to call all of these UFCS style right now since method
  379. // resolution won't implicitly drop the Send+Sync bounds
  380. let mut err = Error::new(ErrorKind::Other, TestError);
  381. assert!(err.get_ref().unwrap().is::<TestError>());
  382. assert_eq!("asdf", err.get_ref().unwrap().description());
  383. assert!(err.get_mut().unwrap().is::<TestError>());
  384. let extracted = err.into_inner().unwrap();
  385. extracted.downcast::<TestError>().unwrap();
  386. }
  387. }