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