1 use crate::utils::Context;
2 
3 use std::{error::Error as StdError, fmt, io};
4 
5 /// Wrap `std::io::Error` with additional message
6 ///
7 /// Keeps the original error kind and stores the original I/O error as `source`.
8 impl<T> Context for Result<T, std::io::Error> {
context(self, message: impl Fn() -> String) -> Self9     fn context(self, message: impl Fn() -> String) -> Self {
10         self.map_err(|e| VerboseError::wrap(e, message()))
11     }
12 }
13 
14 #[derive(Debug)]
15 pub(crate) struct VerboseError {
16     source: io::Error,
17     message: String,
18 }
19 
20 impl VerboseError {
wrap(source: io::Error, message: impl Into<String>) -> io::Error21     pub(crate) fn wrap(source: io::Error, message: impl Into<String>) -> io::Error {
22         io::Error::new(
23             source.kind(),
24             VerboseError {
25                 source,
26                 message: message.into(),
27             },
28         )
29     }
30 }
31 
32 impl fmt::Display for VerboseError {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result33     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34         write!(f, "{}", self.message)
35     }
36 }
37 
38 impl StdError for VerboseError {
source(&self) -> Option<&(dyn StdError + 'static)>39     fn source(&self) -> Option<&(dyn StdError + 'static)> {
40         Some(&self.source)
41     }
42 }
43