1/// A shim which allows a [`std::io::Write`] to be implemented in terms of a [`std::fmt::Write`]
2///
3/// This saves off I/O errors. instead of discarding them
4pub(crate) struct Adapter<W>
5where
6 W: FnMut(&[u8]) -> std::io::Result<()>,
7{
8 writer: W,
9 error: std::io::Result<()>,
10}
11
12impl<W> Adapter<W>
13where
14 W: FnMut(&[u8]) -> std::io::Result<()>,
15{
16 pub(crate) fn new(writer: W) -> Self {
17 Adapter {
18 writer,
19 error: Ok(()),
20 }
21 }
22
23 pub(crate) fn write_fmt(mut self, fmt: std::fmt::Arguments<'_>) -> std::io::Result<()> {
24 match std::fmt::write(&mut self, fmt) {
25 Ok(()) => Ok(()),
26 Err(..) => {
27 // check if the error came from the underlying `Write` or not
28 if self.error.is_err() {
29 self.error
30 } else {
31 Err(std::io::Error::new(
32 std::io::ErrorKind::Other,
33 "formatter error",
34 ))
35 }
36 }
37 }
38 }
39}
40
41impl<W> std::fmt::Write for Adapter<W>
42where
43 W: FnMut(&[u8]) -> std::io::Result<()>,
44{
45 fn write_str(&mut self, s: &str) -> std::fmt::Result {
46 match (self.writer)(s.as_bytes()) {
47 Ok(()) => Ok(()),
48 Err(e: Error) => {
49 self.error = Err(e);
50 Err(std::fmt::Error)
51 }
52 }
53 }
54}
55