blob: e673c26dd5230b0281c0df062f947eddcd311b4c [file] [log] [blame] [edit]
/// 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<W>
where
W: FnMut(&[u8]) -> std::io::Result<()>,
{
writer: W,
error: std::io::Result<()>,
}
impl<W> Adapter<W>
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<W> std::fmt::Write for Adapter<W>
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)
}
}
}
}