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