diff options
author | Garrett Berg <googberg@gmail.com> | 2018-01-31 04:24:28 +0300 |
---|---|---|
committer | Andrew Gallant <jamslam@gmail.com> | 2018-01-31 04:24:28 +0300 |
commit | b03670ee30719163f6c074498c5d17180c883c6c (patch) | |
tree | 525db0c07db8e4ba24d1324100a1d1c79c2a3787 | |
parent | 9775f531be71074bdd5bf5025365f8e6e9efb110 (diff) |
errors: keep context when converting to io::Error
This commit tweaks the `From<walkdir::Error> for io::Error`
implementation to always retain the current context when
constructing the `io::Error`. This differs from the previous
implementation in that the original raw I/O error is no longer
returned.
To compensate, a new method, `into_io_error`, has been
added which returns the original I/O error, if one exists.
We do not consider this a breaking change because the
documentation for the `From` impl always stated that it
existed for ergonomic reasons. Arguably, the implementation
in this commit is a more faithful reflection of that
documentation.
This commit also clears up the public documentation
surrounding the aforementioned methods.
-rw-r--r-- | src/lib.rs | 57 |
1 files changed, 43 insertions, 14 deletions
@@ -1282,12 +1282,13 @@ impl<P> FilterEntry<IntoIter, P> where P: FnMut(&DirEntry) -> bool { /// case, there is no underlying IO error. /// /// To maintain good ergonomics, this type has a -/// `impl From<Error> for std::io::Error` defined so that you may use an -/// [`io::Result`] with methods in this crate if you don't care about accessing -/// the underlying error data in a structured form. +/// [`impl From<Error> for std::io::Error`][impl] defined which preserves the original context. +/// This allows you to use an [`io::Result`] with methods in this crate if you don't care about +/// accessing the underlying error data in a structured form. /// /// [`std::io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html /// [`io::Result`]: https://doc.rust-lang.org/stable/std/io/type.Result.html +/// [impl]: struct.Error.html#impl-From%3CError%3E #[derive(Debug)] pub struct Error { depth: usize, @@ -1346,17 +1347,19 @@ impl Error { self.depth } - /// Inspect the underlying [`io::Error`] if there is one. + /// Inspect the original [`io::Error`] if there is one. /// /// [`None`] is returned if the [`Error`] doesn't correspond to an /// [`io::Error`]. This might happen, for example, when the error was /// produced because a cycle was found in the directory tree while /// following symbolic links. /// - /// This method returns a borrowed value that is bound to the lifetime of - /// the [`Error`]. To obtain an owned value, the [`From`] trait can be used - /// instead, in which case if the [`Error`] being being converted doesn't - /// correspond to an [`io::Error`], a new one will be created. + /// This method returns a borrowed value that is bound to the lifetime of the [`Error`]. To + /// obtain an owned value, the [`into_io_error`] can be used instead. + /// + /// > This is the original [`io::Error`] and is _not_ the same as + /// > [`impl From<Error> for std::io::Error`][impl] which contains additional context about the + /// error. /// /// # Example /// @@ -1400,6 +1403,8 @@ impl Error { /// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html /// [`From`]: https://doc.rust-lang.org/stable/std/convert/trait.From.html /// [`Error`]: struct.Error.html + /// [`into_io_error`]: struct.Error.html#method.into_io_error + /// [impl]: struct.Error.html#impl-From%3CError%3E pub fn io_error(&self) -> Option<&io::Error> { match self.inner { ErrorInner::Io { ref err, .. } => Some(err), @@ -1407,6 +1412,18 @@ impl Error { } } + /// Similar to [`io_error`] except consumes self to convert to the original + /// [`io::Error`] if one exists. + /// + /// [`io_error`]: struct.Error.html#method.io_error + /// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html + pub fn into_io_error(self) -> Option<io::Error> { + match self.inner { + ErrorInner::Io { err, .. } => Some(err), + ErrorInner::Loop { .. } => None, + } + } + fn from_path(depth: usize, pb: PathBuf, err: io::Error) -> Self { Error { depth: depth, @@ -1468,12 +1485,24 @@ impl fmt::Display for Error { } impl From<Error> for io::Error { - fn from(err: Error) -> io::Error { - match err { - Error { inner: ErrorInner::Io { err, .. }, .. } => err, - err @ Error { inner: ErrorInner::Loop { .. }, .. } => { - io::Error::new(io::ErrorKind::Other, err) + /// Convert the [`Error`] to an [`io::Error`], preserving the original [`Error`] as the ["inner + /// error"]. Note that this also makes the display of the error include the context. + /// + /// This is different from [`into_io_error`] which returns the original [`io::Error`]. + /// + /// [`Error`]: struct.Error.html + /// [`io::Error`]: https://doc.rust-lang.org/stable/std/io/struct.Error.html + /// ["inner error"]: https://doc.rust-lang.org/std/io/struct.Error.html#method.into_inner + /// [`into_io_error`]: struct.WalkDir.html#method.into_io_error + fn from(walk_err: Error) -> io::Error { + let kind = match walk_err { + Error { inner: ErrorInner::Io { ref err, .. }, .. } => { + err.kind() } - } + Error { inner: ErrorInner::Loop { .. }, .. } => { + io::ErrorKind::Other + } + }; + io::Error::new(kind, walk_err) } } |