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