/// A shim which allows a [`std::io::Write`] to be implemented in terms of a [`std::fmt::Write`] /// /// This saves off I/O errors. instead of discarding them pub(crate) struct Adapter where W: FnMut(&[u8]) -> std::io::Result<()>, { writer: W, error: std::io::Result<()>, } impl Adapter where W: FnMut(&[u8]) -> std::io::Result<()>, { pub(crate) fn new(writer: W) -> Self { Adapter { writer, error: Ok(()), } } pub(crate) fn write_fmt(mut self, fmt: std::fmt::Arguments<'_>) -> std::io::Result<()> { match std::fmt::write(&mut self, fmt) { Ok(()) => Ok(()), Err(..) => { // check if the error came from the underlying `Write` or not if self.error.is_err() { self.error } else { Err(std::io::Error::new( std::io::ErrorKind::Other, "formatter error", )) } } } } } impl std::fmt::Write for Adapter where W: FnMut(&[u8]) -> std::io::Result<()>, { fn write_str(&mut self, s: &str) -> std::fmt::Result { match (self.writer)(s.as_bytes()) { Ok(()) => Ok(()), Err(e) => { self.error = Err(e); Err(std::fmt::Error) } } } }