]> git.lizzy.rs Git - rust.git/blob - src/libstd/io/error.rs
remove implementation detail from doc
[rust.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 error;
12 use fmt;
13 use result;
14 use sys;
15 use convert::From;
16
17 /// A specialized [`Result`](../result/enum.Result.html) type for I/O
18 /// operations.
19 ///
20 /// This type is broadly used across [`std::io`] for any operation which may
21 /// produce an error.
22 ///
23 /// This typedef is generally used to avoid writing out [`io::Error`] directly and
24 /// is otherwise a direct mapping to [`Result`].
25 ///
26 /// While usual Rust style is to import types directly, aliases of [`Result`]
27 /// often are not, to make it easier to distinguish between them. [`Result`] is
28 /// generally assumed to be [`std::result::Result`][`Result`], and so users of this alias
29 /// will generally use `io::Result` instead of shadowing the prelude's import
30 /// of [`std::result::Result`][`Result`].
31 ///
32 /// [`std::io`]: ../io/index.html
33 /// [`io::Error`]: ../io/struct.Error.html
34 /// [`Result`]: ../result/enum.Result.html
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 ///     io::stdin().read_line(&mut buffer)?;
47 ///
48 ///     Ok(buffer)
49 /// }
50 /// ```
51 #[stable(feature = "rust1", since = "1.0.0")]
52 pub 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`].
60 ///
61 /// [`Read`]: ../io/trait.Read.html
62 /// [`Write`]: ../io/trait.Write.html
63 /// [`Seek`]: ../io/trait.Seek.html
64 /// [`ErrorKind`]: enum.ErrorKind.html
65 #[derive(Debug)]
66 #[stable(feature = "rust1", since = "1.0.0")]
67 pub struct Error {
68     repr: Repr,
69 }
70
71 enum Repr {
72     Os(i32),
73     Simple(ErrorKind),
74     Custom(Box<Custom>),
75 }
76
77 #[derive(Debug)]
78 struct Custom {
79     kind: ErrorKind,
80     error: Box<error::Error+Send+Sync>,
81 }
82
83 /// A list specifying general categories of I/O error.
84 ///
85 /// This list is intended to grow over time and it is not recommended to
86 /// exhaustively match against it.
87 ///
88 /// It is used with the [`io::Error`] type.
89 ///
90 /// [`io::Error`]: struct.Error.html
91 #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
92 #[stable(feature = "rust1", since = "1.0.0")]
93 #[allow(deprecated)]
94 pub enum ErrorKind {
95     /// An entity was not found, often a file.
96     #[stable(feature = "rust1", since = "1.0.0")]
97     NotFound,
98     /// The operation lacked the necessary privileges to complete.
99     #[stable(feature = "rust1", since = "1.0.0")]
100     PermissionDenied,
101     /// The connection was refused by the remote server.
102     #[stable(feature = "rust1", since = "1.0.0")]
103     ConnectionRefused,
104     /// The connection was reset by the remote server.
105     #[stable(feature = "rust1", since = "1.0.0")]
106     ConnectionReset,
107     /// The connection was aborted (terminated) by the remote server.
108     #[stable(feature = "rust1", since = "1.0.0")]
109     ConnectionAborted,
110     /// The network operation failed because it was not connected yet.
111     #[stable(feature = "rust1", since = "1.0.0")]
112     NotConnected,
113     /// A socket address could not be bound because the address is already in
114     /// use elsewhere.
115     #[stable(feature = "rust1", since = "1.0.0")]
116     AddrInUse,
117     /// A nonexistent interface was requested or the requested address was not
118     /// local.
119     #[stable(feature = "rust1", since = "1.0.0")]
120     AddrNotAvailable,
121     /// The operation failed because a pipe was closed.
122     #[stable(feature = "rust1", since = "1.0.0")]
123     BrokenPipe,
124     /// An entity already exists, often a file.
125     #[stable(feature = "rust1", since = "1.0.0")]
126     AlreadyExists,
127     /// The operation needs to block to complete, but the blocking operation was
128     /// requested to not occur.
129     #[stable(feature = "rust1", since = "1.0.0")]
130     WouldBlock,
131     /// A parameter was incorrect.
132     #[stable(feature = "rust1", since = "1.0.0")]
133     InvalidInput,
134     /// Data not valid for the operation were encountered.
135     ///
136     /// Unlike [`InvalidInput`], this typically means that the operation
137     /// parameters were valid, however the error was caused by malformed
138     /// input data.
139     ///
140     /// For example, a function that reads a file into a string will error with
141     /// `InvalidData` if the file's contents are not valid UTF-8.
142     ///
143     /// [`InvalidInput`]: #variant.InvalidInput
144     #[stable(feature = "io_invalid_data", since = "1.2.0")]
145     InvalidData,
146     /// The I/O operation's timeout expired, causing it to be canceled.
147     #[stable(feature = "rust1", since = "1.0.0")]
148     TimedOut,
149     /// An error returned when an operation could not be completed because a
150     /// call to [`write`] returned [`Ok(0)`].
151     ///
152     /// This typically means that an operation could only succeed if it wrote a
153     /// particular number of bytes but only a smaller number of bytes could be
154     /// written.
155     ///
156     /// [`write`]: ../../std/io/trait.Write.html#tymethod.write
157     /// [`Ok(0)`]: ../../std/io/type.Result.html
158     #[stable(feature = "rust1", since = "1.0.0")]
159     WriteZero,
160     /// This operation was interrupted.
161     ///
162     /// Interrupted operations can typically be retried.
163     #[stable(feature = "rust1", since = "1.0.0")]
164     Interrupted,
165     /// Any I/O error not part of this list.
166     #[stable(feature = "rust1", since = "1.0.0")]
167     Other,
168
169     /// An error returned when an operation could not be completed because an
170     /// "end of file" was reached prematurely.
171     ///
172     /// This typically means that an operation could only succeed if it read a
173     /// particular number of bytes but only a smaller number of bytes could be
174     /// read.
175     #[stable(feature = "read_exact", since = "1.6.0")]
176     UnexpectedEof,
177
178     /// A marker variant that tells the compiler that users of this enum cannot
179     /// match it exhaustively.
180     #[unstable(feature = "io_error_internals",
181                reason = "better expressed through extensible enums that this \
182                          enum cannot be exhaustively matched against",
183                issue = "0")]
184     #[doc(hidden)]
185     __Nonexhaustive,
186 }
187
188 impl ErrorKind {
189     fn as_str(&self) -> &'static str {
190         match *self {
191             ErrorKind::NotFound => "entity not found",
192             ErrorKind::PermissionDenied => "permission denied",
193             ErrorKind::ConnectionRefused => "connection refused",
194             ErrorKind::ConnectionReset => "connection reset",
195             ErrorKind::ConnectionAborted => "connection aborted",
196             ErrorKind::NotConnected => "not connected",
197             ErrorKind::AddrInUse => "address in use",
198             ErrorKind::AddrNotAvailable => "address not available",
199             ErrorKind::BrokenPipe => "broken pipe",
200             ErrorKind::AlreadyExists => "entity already exists",
201             ErrorKind::WouldBlock => "operation would block",
202             ErrorKind::InvalidInput => "invalid input parameter",
203             ErrorKind::InvalidData => "invalid data",
204             ErrorKind::TimedOut => "timed out",
205             ErrorKind::WriteZero => "write zero",
206             ErrorKind::Interrupted => "operation interrupted",
207             ErrorKind::Other => "other os error",
208             ErrorKind::UnexpectedEof => "unexpected end of file",
209             ErrorKind::__Nonexhaustive => unreachable!()
210         }
211     }
212 }
213
214 /// Intended for use for errors not exposed to the user, where allocating onto
215 /// the heap (for normal construction via Error::new) is too costly.
216 #[stable(feature = "io_error_from_errorkind", since = "1.14.0")]
217 impl From<ErrorKind> for Error {
218     #[inline]
219     fn from(kind: ErrorKind) -> Error {
220         Error {
221             repr: Repr::Simple(kind)
222         }
223     }
224 }
225
226 impl Error {
227     /// Creates a new I/O error from a known kind of error as well as an
228     /// arbitrary error payload.
229     ///
230     /// This function is used to generically create I/O errors which do not
231     /// originate from the OS itself. The `error` argument is an arbitrary
232     /// payload which will be contained in this `Error`.
233     ///
234     /// # Examples
235     ///
236     /// ```
237     /// use std::io::{Error, ErrorKind};
238     ///
239     /// // errors can be created from strings
240     /// let custom_error = Error::new(ErrorKind::Other, "oh no!");
241     ///
242     /// // errors can also be created from other errors
243     /// let custom_error2 = Error::new(ErrorKind::Interrupted, custom_error);
244     /// ```
245     #[stable(feature = "rust1", since = "1.0.0")]
246     pub fn new<E>(kind: ErrorKind, error: E) -> Error
247         where E: Into<Box<error::Error+Send+Sync>>
248     {
249         Self::_new(kind, error.into())
250     }
251
252     fn _new(kind: ErrorKind, error: Box<error::Error+Send+Sync>) -> Error {
253         Error {
254             repr: Repr::Custom(Box::new(Custom {
255                 kind,
256                 error,
257             }))
258         }
259     }
260
261     /// Returns an error representing the last OS error which occurred.
262     ///
263     /// This function reads the value of `errno` for the target platform (e.g.
264     /// `GetLastError` on Windows) and will return a corresponding instance of
265     /// `Error` for the error code.
266     ///
267     /// # Examples
268     ///
269     /// ```
270     /// use std::io::Error;
271     ///
272     /// println!("last OS error: {:?}", Error::last_os_error());
273     /// ```
274     #[stable(feature = "rust1", since = "1.0.0")]
275     pub fn last_os_error() -> Error {
276         Error::from_raw_os_error(sys::os::errno() as i32)
277     }
278
279     /// Creates a new instance of an `Error` from a particular OS error code.
280     ///
281     /// # Examples
282     ///
283     /// On Linux:
284     ///
285     /// ```
286     /// # if cfg!(target_os = "linux") {
287     /// use std::io;
288     ///
289     /// let error = io::Error::from_raw_os_error(98);
290     /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
291     /// # }
292     /// ```
293     ///
294     /// On Windows:
295     ///
296     /// ```
297     /// # if cfg!(windows) {
298     /// use std::io;
299     ///
300     /// let error = io::Error::from_raw_os_error(10048);
301     /// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
302     /// # }
303     /// ```
304     #[stable(feature = "rust1", since = "1.0.0")]
305     pub fn from_raw_os_error(code: i32) -> Error {
306         Error { repr: Repr::Os(code) }
307     }
308
309     /// Returns the OS error that this error represents (if any).
310     ///
311     /// If this `Error` was constructed via `last_os_error` or
312     /// `from_raw_os_error`, then this function will return `Some`, otherwise
313     /// it will return `None`.
314     ///
315     /// # Examples
316     ///
317     /// ```
318     /// use std::io::{Error, ErrorKind};
319     ///
320     /// fn print_os_error(err: &Error) {
321     ///     if let Some(raw_os_err) = err.raw_os_error() {
322     ///         println!("raw OS error: {:?}", raw_os_err);
323     ///     } else {
324     ///         println!("Not an OS error");
325     ///     }
326     /// }
327     ///
328     /// fn main() {
329     ///     // Will print "raw OS error: ...".
330     ///     print_os_error(&Error::last_os_error());
331     ///     // Will print "Not an OS error".
332     ///     print_os_error(&Error::new(ErrorKind::Other, "oh no!"));
333     /// }
334     /// ```
335     #[stable(feature = "rust1", since = "1.0.0")]
336     pub fn raw_os_error(&self) -> Option<i32> {
337         match self.repr {
338             Repr::Os(i) => Some(i),
339             Repr::Custom(..) => None,
340             Repr::Simple(..) => None,
341         }
342     }
343
344     /// Returns a reference to the inner error wrapped by this error (if any).
345     ///
346     /// If this `Error` was constructed via `new` then this function will
347     /// return `Some`, otherwise it will return `None`.
348     ///
349     /// # Examples
350     ///
351     /// ```
352     /// use std::io::{Error, ErrorKind};
353     ///
354     /// fn print_error(err: &Error) {
355     ///     if let Some(inner_err) = err.get_ref() {
356     ///         println!("Inner error: {:?}", inner_err);
357     ///     } else {
358     ///         println!("No inner error");
359     ///     }
360     /// }
361     ///
362     /// fn main() {
363     ///     // Will print "No inner error".
364     ///     print_error(&Error::last_os_error());
365     ///     // Will print "Inner error: ...".
366     ///     print_error(&Error::new(ErrorKind::Other, "oh no!"));
367     /// }
368     /// ```
369     #[stable(feature = "io_error_inner", since = "1.3.0")]
370     pub fn get_ref(&self) -> Option<&(error::Error+Send+Sync+'static)> {
371         match self.repr {
372             Repr::Os(..) => None,
373             Repr::Simple(..) => None,
374             Repr::Custom(ref c) => Some(&*c.error),
375         }
376     }
377
378     /// Returns a mutable reference to the inner error wrapped by this error
379     /// (if any).
380     ///
381     /// If this `Error` was constructed via `new` then this function will
382     /// return `Some`, otherwise it will return `None`.
383     ///
384     /// # Examples
385     ///
386     /// ```
387     /// use std::io::{Error, ErrorKind};
388     /// use std::{error, fmt};
389     /// use std::fmt::Display;
390     ///
391     /// #[derive(Debug)]
392     /// struct MyError {
393     ///     v: String,
394     /// }
395     ///
396     /// impl MyError {
397     ///     fn new() -> MyError {
398     ///         MyError {
399     ///             v: "oh no!".to_string()
400     ///         }
401     ///     }
402     ///
403     ///     fn change_message(&mut self, new_message: &str) {
404     ///         self.v = new_message.to_string();
405     ///     }
406     /// }
407     ///
408     /// impl error::Error for MyError {
409     ///     fn description(&self) -> &str { &self.v }
410     /// }
411     ///
412     /// impl Display for MyError {
413     ///     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
414     ///         write!(f, "MyError: {}", &self.v)
415     ///     }
416     /// }
417     ///
418     /// fn change_error(mut err: Error) -> Error {
419     ///     if let Some(inner_err) = err.get_mut() {
420     ///         inner_err.downcast_mut::<MyError>().unwrap().change_message("I've been changed!");
421     ///     }
422     ///     err
423     /// }
424     ///
425     /// fn print_error(err: &Error) {
426     ///     if let Some(inner_err) = err.get_ref() {
427     ///         println!("Inner error: {}", inner_err);
428     ///     } else {
429     ///         println!("No inner error");
430     ///     }
431     /// }
432     ///
433     /// fn main() {
434     ///     // Will print "No inner error".
435     ///     print_error(&change_error(Error::last_os_error()));
436     ///     // Will print "Inner error: ...".
437     ///     print_error(&change_error(Error::new(ErrorKind::Other, MyError::new())));
438     /// }
439     /// ```
440     #[stable(feature = "io_error_inner", since = "1.3.0")]
441     pub fn get_mut(&mut self) -> Option<&mut (error::Error+Send+Sync+'static)> {
442         match self.repr {
443             Repr::Os(..) => None,
444             Repr::Simple(..) => None,
445             Repr::Custom(ref mut c) => Some(&mut *c.error),
446         }
447     }
448
449     /// Consumes the `Error`, returning its inner error (if any).
450     ///
451     /// If this `Error` was constructed via `new` then this function will
452     /// return `Some`, otherwise it will return `None`.
453     ///
454     /// # Examples
455     ///
456     /// ```
457     /// use std::io::{Error, ErrorKind};
458     ///
459     /// fn print_error(err: Error) {
460     ///     if let Some(inner_err) = err.into_inner() {
461     ///         println!("Inner error: {}", inner_err);
462     ///     } else {
463     ///         println!("No inner error");
464     ///     }
465     /// }
466     ///
467     /// fn main() {
468     ///     // Will print "No inner error".
469     ///     print_error(Error::last_os_error());
470     ///     // Will print "Inner error: ...".
471     ///     print_error(Error::new(ErrorKind::Other, "oh no!"));
472     /// }
473     /// ```
474     #[stable(feature = "io_error_inner", since = "1.3.0")]
475     pub fn into_inner(self) -> Option<Box<error::Error+Send+Sync>> {
476         match self.repr {
477             Repr::Os(..) => None,
478             Repr::Simple(..) => None,
479             Repr::Custom(c) => Some(c.error)
480         }
481     }
482
483     /// Returns the corresponding `ErrorKind` for this error.
484     ///
485     /// # Examples
486     ///
487     /// ```
488     /// use std::io::{Error, ErrorKind};
489     ///
490     /// fn print_error(err: Error) {
491     ///     println!("{:?}", err.kind());
492     /// }
493     ///
494     /// fn main() {
495     ///     // Will print "No inner error".
496     ///     print_error(Error::last_os_error());
497     ///     // Will print "Inner error: ...".
498     ///     print_error(Error::new(ErrorKind::AddrInUse, "oh no!"));
499     /// }
500     /// ```
501     #[stable(feature = "rust1", since = "1.0.0")]
502     pub fn kind(&self) -> ErrorKind {
503         match self.repr {
504             Repr::Os(code) => sys::decode_error_kind(code),
505             Repr::Custom(ref c) => c.kind,
506             Repr::Simple(kind) => kind,
507         }
508     }
509 }
510
511 impl fmt::Debug for Repr {
512     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
513         match *self {
514             Repr::Os(ref code) =>
515                 fmt.debug_struct("Os").field("code", code)
516                    .field("message", &sys::os::error_string(*code)).finish(),
517             Repr::Custom(ref c) => fmt.debug_tuple("Custom").field(c).finish(),
518             Repr::Simple(kind) => fmt.debug_tuple("Kind").field(&kind).finish(),
519         }
520     }
521 }
522
523 #[stable(feature = "rust1", since = "1.0.0")]
524 impl fmt::Display for Error {
525     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
526         match self.repr {
527             Repr::Os(code) => {
528                 let detail = sys::os::error_string(code);
529                 write!(fmt, "{} (os error {})", detail, code)
530             }
531             Repr::Custom(ref c) => c.error.fmt(fmt),
532             Repr::Simple(kind) => write!(fmt, "{}", kind.as_str()),
533         }
534     }
535 }
536
537 #[stable(feature = "rust1", since = "1.0.0")]
538 impl error::Error for Error {
539     fn description(&self) -> &str {
540         match self.repr {
541             Repr::Os(..) | Repr::Simple(..) => self.kind().as_str(),
542             Repr::Custom(ref c) => c.error.description(),
543         }
544     }
545
546     fn cause(&self) -> Option<&error::Error> {
547         match self.repr {
548             Repr::Os(..) => None,
549             Repr::Simple(..) => None,
550             Repr::Custom(ref c) => c.error.cause(),
551         }
552     }
553 }
554
555 fn _assert_error_is_sync_send() {
556     fn _is_sync_send<T: Sync+Send>() {}
557     _is_sync_send::<Error>();
558 }
559
560 #[cfg(test)]
561 mod test {
562     use super::{Error, ErrorKind};
563     use error;
564     use fmt;
565     use sys::os::error_string;
566
567     #[test]
568     fn test_debug_error() {
569         let code = 6;
570         let msg = error_string(code);
571         let err = Error { repr: super::Repr::Os(code) };
572         let expected = format!("Error {{ repr: Os {{ code: {:?}, message: {:?} }} }}", code, msg);
573         assert_eq!(format!("{:?}", err), expected);
574     }
575
576     #[test]
577     fn test_downcasting() {
578         #[derive(Debug)]
579         struct TestError;
580
581         impl fmt::Display for TestError {
582             fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result {
583                 Ok(())
584             }
585         }
586
587         impl error::Error for TestError {
588             fn description(&self) -> &str {
589                 "asdf"
590             }
591         }
592
593         // we have to call all of these UFCS style right now since method
594         // resolution won't implicitly drop the Send+Sync bounds
595         let mut err = Error::new(ErrorKind::Other, TestError);
596         assert!(err.get_ref().unwrap().is::<TestError>());
597         assert_eq!("asdf", err.get_ref().unwrap().description());
598         assert!(err.get_mut().unwrap().is::<TestError>());
599         let extracted = err.into_inner().unwrap();
600         extracted.downcast::<TestError>().unwrap();
601     }
602 }