1 use std::path::PathBuf;
2 use std::{error, fmt, io};
3 
4 #[derive(Debug)]
5 struct PathError {
6     path: PathBuf,
7     err: io::Error,
8 }
9 
10 impl fmt::Display for PathError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result11     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12         write!(f, "{} at path {:?}", self.err, self.path)
13     }
14 }
15 
16 impl error::Error for PathError {
source(&self) -> Option<&(dyn error::Error + 'static)>17     fn source(&self) -> Option<&(dyn error::Error + 'static)> {
18         self.err.source()
19     }
20 }
21 
22 pub(crate) trait IoResultExt<T> {
with_err_path<F, P>(self, path: F) -> Self where F: FnOnce() -> P, P: Into<PathBuf>23     fn with_err_path<F, P>(self, path: F) -> Self
24     where
25         F: FnOnce() -> P,
26         P: Into<PathBuf>;
27 }
28 
29 impl<T> IoResultExt<T> for Result<T, io::Error> {
with_err_path<F, P>(self, path: F) -> Self where F: FnOnce() -> P, P: Into<PathBuf>,30     fn with_err_path<F, P>(self, path: F) -> Self
31     where
32         F: FnOnce() -> P,
33         P: Into<PathBuf>,
34     {
35         self.map_err(|e| {
36             io::Error::new(
37                 e.kind(),
38                 PathError {
39                     path: path().into(),
40                     err: e,
41                 },
42             )
43         })
44     }
45 }
46