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 |
4 | pub(crate) struct Adapter<W> |
5 | where |
6 | W: FnMut(&[u8]) -> std::io::Result<()>, |
7 | { |
8 | writer: W, |
9 | error: std::io::Result<()>, |
10 | } |
11 | |
12 | impl<W> Adapter<W> |
13 | where |
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 | |
41 | impl<W> std::fmt::Write for Adapter<W> |
42 | where |
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 | |