error.rs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. #[cfg(feature="alloc")] use alloc::boxed::Box;
  11. #[cfg(not(feature="alloc"))] use ::FakeBox as Box;
  12. use core::convert::Into;
  13. use core::fmt;
  14. use core::marker::{Send, Sync};
  15. use core::option::Option::{self, Some, None};
  16. use core::result;
  17. #[cfg(feature="collections")] use collections::string::String;
  18. #[cfg(not(feature="collections"))] use ::ErrorString as String;
  19. /// A specialized [`Result`](../result/enum.Result.html) type for I/O
  20. /// operations.
  21. ///
  22. /// This type is broadly used across `std::io` for any operation which may
  23. /// produce an error.
  24. ///
  25. /// This typedef is generally used to avoid writing out `io::Error` directly and
  26. /// is otherwise a direct mapping to `Result`.
  27. ///
  28. /// While usual Rust style is to import types directly, aliases of `Result`
  29. /// often are not, to make it easier to distinguish between them. `Result` is
  30. /// generally assumed to be `std::result::Result`, and so users of this alias
  31. /// will generally use `io::Result` instead of shadowing the prelude's import
  32. /// of `std::result::Result`.
  33. ///
  34. /// # Examples
  35. ///
  36. /// A convenience function that bubbles an `io::Result` to its caller:
  37. ///
  38. /// ```
  39. /// use std::io;
  40. ///
  41. /// fn get_string() -> io::Result<String> {
  42. /// let mut buffer = String::new();
  43. ///
  44. /// try!(io::stdin().read_line(&mut buffer));
  45. ///
  46. /// Ok(buffer)
  47. /// }
  48. /// ```
  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. pub struct Error {
  58. repr: Repr,
  59. }
  60. enum Repr {
  61. Os(i32),
  62. #[cfg(feature="alloc")]
  63. Custom(Box<Custom>),
  64. #[cfg(not(feature="alloc"))]
  65. Custom(Custom),
  66. }
  67. #[derive(Debug)]
  68. struct Custom {
  69. kind: ErrorKind,
  70. error: String,
  71. }
  72. /// A list specifying general categories of I/O error.
  73. ///
  74. /// This list is intended to grow over time and it is not recommended to
  75. /// exhaustively match against it.
  76. #[derive(Copy, PartialEq, Eq, Clone, Debug)]
  77. #[allow(deprecated)]
  78. pub enum ErrorKind {
  79. /// An entity was not found, often a file.
  80. NotFound,
  81. /// The operation lacked the necessary privileges to complete.
  82. PermissionDenied,
  83. /// The connection was refused by the remote server.
  84. ConnectionRefused,
  85. /// The connection was reset by the remote server.
  86. ConnectionReset,
  87. /// The connection was aborted (terminated) by the remote server.
  88. ConnectionAborted,
  89. /// The network operation failed because it was not connected yet.
  90. NotConnected,
  91. /// A socket address could not be bound because the address is already in
  92. /// use elsewhere.
  93. AddrInUse,
  94. /// A nonexistent interface was requested or the requested address was not
  95. /// local.
  96. AddrNotAvailable,
  97. /// The operation failed because a pipe was closed.
  98. BrokenPipe,
  99. /// An entity already exists, often a file.
  100. AlreadyExists,
  101. /// The operation needs to block to complete, but the blocking operation was
  102. /// requested to not occur.
  103. WouldBlock,
  104. /// A parameter was incorrect.
  105. InvalidInput,
  106. /// Data not valid for the operation were encountered.
  107. ///
  108. /// Unlike `InvalidInput`, this typically means that the operation
  109. /// parameters were valid, however the error was caused by malformed
  110. /// input data.
  111. ///
  112. /// For example, a function that reads a file into a string will error with
  113. /// `InvalidData` if the file's contents are not valid UTF-8.
  114. InvalidData,
  115. /// The I/O operation's timeout expired, causing it to be canceled.
  116. TimedOut,
  117. /// An error returned when an operation could not be completed because a
  118. /// call to `write` returned `Ok(0)`.
  119. ///
  120. /// This typically means that an operation could only succeed if it wrote a
  121. /// particular number of bytes but only a smaller number of bytes could be
  122. /// written.
  123. WriteZero,
  124. /// This operation was interrupted.
  125. ///
  126. /// Interrupted operations can typically be retried.
  127. Interrupted,
  128. /// Any I/O error not part of this list.
  129. Other,
  130. /// An error returned when an operation could not be completed because an
  131. /// "end of file" was reached prematurely.
  132. ///
  133. /// This typically means that an operation could only succeed if it read a
  134. /// particular number of bytes but only a smaller number of bytes could be
  135. /// read.
  136. UnexpectedEof,
  137. /// Any I/O error not part of this list.
  138. #[doc(hidden)]
  139. __Nonexhaustive,
  140. }
  141. impl Error {
  142. /// Creates a new I/O error from a known kind of error as well as an
  143. /// arbitrary error payload.
  144. ///
  145. /// This function is used to generically create I/O errors which do not
  146. /// originate from the OS itself. The `error` argument is an arbitrary
  147. /// payload which will be contained in this `Error`.
  148. ///
  149. /// # Examples
  150. ///
  151. /// ```
  152. /// use std::io::{Error, ErrorKind};
  153. ///
  154. /// // errors can be created from strings
  155. /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
  156. ///
  157. /// // errors can also be created from other errors
  158. /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
  159. /// ```
  160. pub fn new<E>(kind: ErrorKind, error: E) -> Error
  161. where E: Into<String>
  162. {
  163. Self::_new(kind, error.into())
  164. }
  165. fn _new(kind: ErrorKind, error: String) -> Error {
  166. Error {
  167. repr: Repr::Custom(Box::new(Custom {
  168. kind: kind,
  169. error: error,
  170. }))
  171. }
  172. }
  173. /// Creates a new instance of an `Error` from a particular OS error code.
  174. pub fn from_raw_os_error(code: i32) -> Error {
  175. Error { repr: Repr::Os(code) }
  176. }
  177. /// Returns the OS error that this error represents (if any).
  178. ///
  179. /// If this `Error` was constructed via `last_os_error` or
  180. /// `from_raw_os_error`, then this function will return `Some`, otherwise
  181. /// it will return `None`.
  182. pub fn raw_os_error(&self) -> Option<i32> {
  183. match self.repr {
  184. Repr::Os(i) => Some(i),
  185. Repr::Custom(..) => None,
  186. }
  187. }
  188. /// Returns a reference to the inner error wrapped by this error (if any).
  189. ///
  190. /// If this `Error` was constructed via `new` then this function will
  191. /// return `Some`, otherwise it will return `None`.
  192. pub fn get_ref(&self) -> Option<&String> {
  193. match self.repr {
  194. Repr::Os(..) => None,
  195. Repr::Custom(ref c) => Some(&c.error),
  196. }
  197. }
  198. /// Returns a mutable reference to the inner error wrapped by this error
  199. /// (if any).
  200. ///
  201. /// If this `Error` was constructed via `new` then this function will
  202. /// return `Some`, otherwise it will return `None`.
  203. pub fn get_mut(&mut self) -> Option<&mut String> {
  204. match self.repr {
  205. Repr::Os(..) => None,
  206. Repr::Custom(ref mut c) => Some(&mut c.error),
  207. }
  208. }
  209. /// Consumes the `Error`, returning its inner error (if any).
  210. ///
  211. /// If this `Error` was constructed via `new` then this function will
  212. /// return `Some`, otherwise it will return `None`.
  213. pub fn into_inner(self) -> Option<String> {
  214. match self.repr {
  215. Repr::Os(..) => None,
  216. Repr::Custom(c) => Some(c.error)
  217. }
  218. }
  219. /// Returns the corresponding `ErrorKind` for this error.
  220. pub fn kind(&self) -> ErrorKind {
  221. match self.repr {
  222. Repr::Os(_code) => ErrorKind::Other,
  223. Repr::Custom(ref c) => c.kind,
  224. }
  225. }
  226. }
  227. impl fmt::Debug for Repr {
  228. fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
  229. match *self {
  230. Repr::Os(ref code) =>
  231. fmt.debug_struct("Os").field("code", code).finish(),
  232. Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
  233. }
  234. }
  235. }
  236. impl fmt::Display for Error {
  237. fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
  238. match self.repr {
  239. Repr::Os(code) => {
  240. write!(fmt, "os error {}", code)
  241. }
  242. Repr::Custom(ref c) => c.error.fmt(fmt),
  243. }
  244. }
  245. }
  246. fn _assert_error_is_sync_send() {
  247. fn _is_sync_send<T: Sync+Send>() {}
  248. _is_sync_send::<Error>();
  249. }
  250. #[cfg(test)]
  251. mod test {
  252. use prelude::v1::*;
  253. use super::{Error, ErrorKind};
  254. use error;
  255. use error::Error as error_Error;
  256. use fmt;
  257. use sys::os::error_string;
  258. #[test]
  259. fn test_debug_error() {
  260. let code = 6;
  261. let msg = error_string(code);
  262. let err = Error { repr: super::Repr::Os(code) };
  263. let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
  264. assert_eq!(format!("{:?}", err), expected);
  265. }
  266. #[test]
  267. fn test_downcasting() {
  268. #[derive(Debug)]
  269. struct TestError;
  270. impl fmt::Display for TestError {
  271. fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
  272. Ok(())
  273. }
  274. }
  275. impl error::Error for TestError {
  276. fn description(&self) -> &str {
  277. "asdf"
  278. }
  279. }
  280. // we have to call all of these UFCS style right now since method
  281. // resolution won't implicitly drop the Send+Sync bounds
  282. let mut err = Error::new(ErrorKind::Other, TestError);
  283. assert!(err.get_ref().unwrap().is::<TestError>());
  284. assert_eq!("asdf", err.get_ref().unwrap().description());
  285. assert!(err.get_mut().unwrap().is::<TestError>());
  286. let extracted = err.into_inner().unwrap();
  287. extracted.downcast::<TestError>().unwrap();
  288. }
  289. }