]> git.proxmox.com Git - rustc.git/blob - src/libstd/io/error.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.git] / src / libstd / io / error.rs
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
11 use boxed::Box;
12 use convert::Into;
13 use error;
14 use fmt;
15 use marker::{Send, Sync};
16 use option::Option::{self, Some, None};
17 use result;
18 use sys;
19
20 /// A type for results generated by I/O related functions where the `Err` type
21 /// is hard-wired to `io::Error`.
22 ///
23 /// This typedef is generally used to avoid writing out `io::Error` directly and
24 /// is otherwise a direct mapping to `std::result::Result`.
25 #[stable(feature = "rust1", since = "1.0.0")]
26 pub type Result<T> = result::Result<T, Error>;
27
28 /// The error type for I/O operations of the `Read`, `Write`, `Seek`, and
29 /// associated traits.
30 ///
31 /// Errors mostly originate from the underlying OS, but custom instances of
32 /// `Error` can be created with crafted error messages and a particular value of
33 /// `ErrorKind`.
34 #[derive(Debug)]
35 #[stable(feature = "rust1", since = "1.0.0")]
36 pub struct Error {
37 repr: Repr,
38 }
39
40 enum Repr {
41 Os(i32),
42 Custom(Box<Custom>),
43 }
44
45 #[derive(Debug)]
46 struct Custom {
47 kind: ErrorKind,
48 error: Box<error::Error+Send+Sync>,
49 }
50
51 /// A list specifying general categories of I/O error.
52 ///
53 /// This list is intended to grow over time and it is not recommended to
54 /// exhaustively match against it.
55 #[derive(Copy, PartialEq, Eq, Clone, Debug)]
56 #[stable(feature = "rust1", since = "1.0.0")]
57 pub enum ErrorKind {
58 /// An entity was not found, often a file.
59 #[stable(feature = "rust1", since = "1.0.0")]
60 NotFound,
61 /// The operation lacked the necessary privileges to complete.
62 #[stable(feature = "rust1", since = "1.0.0")]
63 PermissionDenied,
64 /// The connection was refused by the remote server.
65 #[stable(feature = "rust1", since = "1.0.0")]
66 ConnectionRefused,
67 /// The connection was reset by the remote server.
68 #[stable(feature = "rust1", since = "1.0.0")]
69 ConnectionReset,
70 /// The connection was aborted (terminated) by the remote server.
71 #[stable(feature = "rust1", since = "1.0.0")]
72 ConnectionAborted,
73 /// The network operation failed because it was not connected yet.
74 #[stable(feature = "rust1", since = "1.0.0")]
75 NotConnected,
76 /// A socket address could not be bound because the address is already in
77 /// use elsewhere.
78 #[stable(feature = "rust1", since = "1.0.0")]
79 AddrInUse,
80 /// A nonexistent interface was requested or the requested address was not
81 /// local.
82 #[stable(feature = "rust1", since = "1.0.0")]
83 AddrNotAvailable,
84 /// The operation failed because a pipe was closed.
85 #[stable(feature = "rust1", since = "1.0.0")]
86 BrokenPipe,
87 /// An entity already exists, often a file.
88 #[stable(feature = "rust1", since = "1.0.0")]
89 AlreadyExists,
90 /// The operation needs to block to complete, but the blocking operation was
91 /// requested to not occur.
92 #[stable(feature = "rust1", since = "1.0.0")]
93 WouldBlock,
94 /// A parameter was incorrect.
95 #[stable(feature = "rust1", since = "1.0.0")]
96 InvalidInput,
97 /// Data not valid for the operation were encountered.
98 ///
99 /// Unlike `InvalidInput`, this typically means that the operation
100 /// parameters were valid, however the error was caused by malformed
101 /// input data.
102 #[stable(feature = "io_invalid_data", since = "1.2.0")]
103 InvalidData,
104 /// The I/O operation's timeout expired, causing it to be canceled.
105 #[stable(feature = "rust1", since = "1.0.0")]
106 TimedOut,
107 /// An error returned when an operation could not be completed because a
108 /// call to `write` returned `Ok(0)`.
109 ///
110 /// This typically means that an operation could only succeed if it wrote a
111 /// particular number of bytes but only a smaller number of bytes could be
112 /// written.
113 #[stable(feature = "rust1", since = "1.0.0")]
114 WriteZero,
115 /// This operation was interrupted.
116 ///
117 /// Interrupted operations can typically be retried.
118 #[stable(feature = "rust1", since = "1.0.0")]
119 Interrupted,
120 /// Any I/O error not part of this list.
121 #[stable(feature = "rust1", since = "1.0.0")]
122 Other,
123
124 /// Any I/O error not part of this list.
125 #[unstable(feature = "io_error_internals",
126 reason = "better expressed through extensible enums that this \
127 enum cannot be exhaustively matched against")]
128 #[doc(hidden)]
129 __Nonexhaustive,
130 }
131
132 impl Error {
133 /// Creates a new I/O error from a known kind of error as well as an
134 /// arbitrary error payload.
135 ///
136 /// This function is used to generically create I/O errors which do not
137 /// originate from the OS itself. The `error` argument is an arbitrary
138 /// payload which will be contained in this `Error`.
139 ///
140 /// # Examples
141 ///
142 /// ```
143 /// use std::io::{Error, ErrorKind};
144 ///
145 /// // errors can be created from strings
146 /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
147 ///
148 /// // errors can also be created from other errors
149 /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
150 /// ```
151 #[stable(feature = "rust1", since = "1.0.0")]
152 pub fn new<E>(kind: ErrorKind, error: E) -> Error
153 where E: Into<Box<error::Error+Send+Sync>>
154 {
155 Error {
156 repr: Repr::Custom(Box::new(Custom {
157 kind: kind,
158 error: error.into(),
159 }))
160 }
161 }
162
163 /// Returns an error representing the last OS error which occurred.
164 ///
165 /// This function reads the value of `errno` for the target platform (e.g.
166 /// `GetLastError` on Windows) and will return a corresponding instance of
167 /// `Error` for the error code.
168 #[stable(feature = "rust1", since = "1.0.0")]
169 pub fn last_os_error() -> Error {
170 Error::from_raw_os_error(sys::os::errno() as i32)
171 }
172
173 /// Creates a new instance of an `Error` from a particular OS error code.
174 #[stable(feature = "rust1", since = "1.0.0")]
175 pub fn from_raw_os_error(code: i32) -> Error {
176 Error { repr: Repr::Os(code) }
177 }
178
179 /// Returns the OS error that this error represents (if any).
180 ///
181 /// If this `Error` was constructed via `last_os_error` or
182 /// `from_raw_os_error`, then this function will return `Some`, otherwise
183 /// it will return `None`.
184 #[stable(feature = "rust1", since = "1.0.0")]
185 pub fn raw_os_error(&self) -> Option<i32> {
186 match self.repr {
187 Repr::Os(i) => Some(i),
188 Repr::Custom(..) => None,
189 }
190 }
191
192 /// Returns a reference to the inner error wrapped by this error (if any).
193 ///
194 /// If this `Error` was constructed via `new` then this function will
195 /// return `Some`, otherwise it will return `None`.
196 #[unstable(feature = "io_error_inner",
197 reason = "recently added and requires UFCS to downcast")]
198 pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
199 match self.repr {
200 Repr::Os(..) => None,
201 Repr::Custom(ref c) => Some(&*c.error),
202 }
203 }
204
205 /// Returns a mutable reference to the inner error wrapped by this error
206 /// (if any).
207 ///
208 /// If this `Error` was constructed via `new` then this function will
209 /// return `Some`, otherwise it will return `None`.
210 #[unstable(feature = "io_error_inner",
211 reason = "recently added and requires UFCS to downcast")]
212 pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
213 match self.repr {
214 Repr::Os(..) => None,
215 Repr::Custom(ref mut c) => Some(&mut *c.error),
216 }
217 }
218
219 /// Consumes the `Error`, returning its inner error (if any).
220 ///
221 /// If this `Error` was constructed via `new` then this function will
222 /// return `Some`, otherwise it will return `None`.
223 #[unstable(feature = "io_error_inner",
224 reason = "recently added and requires UFCS to downcast")]
225 pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
226 match self.repr {
227 Repr::Os(..) => None,
228 Repr::Custom(c) => Some(c.error)
229 }
230 }
231
232 /// Returns the corresponding `ErrorKind` for this error.
233 #[stable(feature = "rust1", since = "1.0.0")]
234 pub fn kind(&self) -> ErrorKind {
235 match self.repr {
236 Repr::Os(code) => sys::decode_error_kind(code),
237 Repr::Custom(ref c) => c.kind,
238 }
239 }
240 }
241
242 impl fmt::Debug for Repr {
243 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
244 match self {
245 &Repr::Os(ref code) =>
246 fmt.debug_struct("Os").field("code", code)
247 .field("message", &sys::os::error_string(*code)).finish(),
248 &Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
249 }
250 }
251 }
252
253 #[stable(feature = "rust1", since = "1.0.0")]
254 impl fmt::Display for Error {
255 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
256 match self.repr {
257 Repr::Os(code) => {
258 let detail = sys::os::error_string(code);
259 write!(fmt, "{} (os error {})", detail, code)
260 }
261 Repr::Custom(ref c) => c.error.fmt(fmt),
262 }
263 }
264 }
265
266 #[stable(feature = "rust1", since = "1.0.0")]
267 impl error::Error for Error {
268 fn description(&self) -> &str {
269 match self.repr {
270 Repr::Os(..) => "os error",
271 Repr::Custom(ref c) => c.error.description(),
272 }
273 }
274
275 fn cause(&self) -> Option<&error::Error> {
276 match self.repr {
277 Repr::Os(..) => None,
278 Repr::Custom(ref c) => c.error.cause(),
279 }
280 }
281 }
282
283 fn _assert_error_is_sync_send() {
284 fn _is_sync_send<T: Sync+Send>() {}
285 _is_sync_send::<Error>();
286 }
287
288 #[cfg(test)]
289 mod test {
290 use prelude::v1::*;
291 use super::{Error, ErrorKind};
292 use error;
293 use error::Error as error_Error;
294 use fmt;
295 use sys::os::error_string;
296
297 #[test]
298 fn test_debug_error() {
299 let code = 6;
300 let msg = error_string(code);
301 let err = Error { repr: super::Repr::Os(code) };
302 let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
303 assert_eq!(format!("{:?}", err), expected);
304 }
305
306 #[test]
307 fn test_downcasting() {
308 #[derive(Debug)]
309 struct TestError;
310
311 impl fmt::Display for TestError {
312 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
313 Ok(())
314 }
315 }
316
317 impl error::Error for TestError {
318 fn description(&self) -> &str {
319 "asdf"
320 }
321 }
322
323 // we have to call all of these UFCS style right now since method
324 // resolution won't implicitly drop the Send+Sync bounds
325 let mut err = Error::new(ErrorKind::Other, TestError);
326 assert!(error::Error::is::<TestError>(err.get_ref().unwrap()));
327 assert_eq!("asdf", err.get_ref().unwrap().description());
328 assert!(error::Error::is::<TestError>(err.get_mut().unwrap()));
329 let extracted = err.into_inner().unwrap();
330 error::Error::downcast::<TestError>(extracted).unwrap();
331 }
332 }