Skip to main content

ax_io/write/
mod.rs

1use core::fmt;
2
3use crate::{Error, Result};
4
5mod impls;
6
7pub(crate) fn default_write_fmt<W: Write + ?Sized>(
8    this: &mut W,
9    args: fmt::Arguments<'_>,
10) -> Result<()> {
11    // Create a shim which translates a `Write` to a `fmt::Write` and saves off
12    // I/O errors, instead of discarding them.
13    struct Adapter<'a, T: ?Sized + 'a> {
14        inner: &'a mut T,
15        error: Result<()>,
16    }
17
18    impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
19        fn write_str(&mut self, s: &str) -> fmt::Result {
20            match self.inner.write_all(s.as_bytes()) {
21                Ok(()) => Ok(()),
22                Err(e) => {
23                    self.error = Err(e);
24                    Err(fmt::Error)
25                }
26            }
27        }
28    }
29
30    let mut output = Adapter {
31        inner: this,
32        error: Ok(()),
33    };
34    match fmt::write(&mut output, args) {
35        Ok(()) => Ok(()),
36        Err(..) => {
37            // Check whether the error came from the underlying `Write`.
38            if output.error.is_err() {
39                output.error
40            } else {
41                // This shouldn't happen: the underlying stream did not error,
42                // but somehow the formatter still errored?
43                panic!(
44                    "a formatting trait implementation returned an error when the underlying \
45                     stream did not"
46                );
47            }
48        }
49    }
50}
51
52/// A trait for objects which are byte-oriented sinks.
53///
54/// See [`std::io::Write`] for more details.
55pub trait Write {
56    /// Write a buffer into this writer, returning how many bytes were written.
57    fn write(&mut self, buf: &[u8]) -> Result<usize>;
58
59    /// Flush this output stream, ensuring that all intermediately buffered
60    /// contents reach their destination.
61    fn flush(&mut self) -> Result<()>;
62
63    /// Attempts to write an entire buffer into this writer.
64    fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
65        while !buf.is_empty() {
66            match self.write(buf) {
67                Ok(0) => return Err(Error::WriteZero),
68                Ok(n) => buf = &buf[n..],
69                Err(e) if e.canonicalize() == Error::Interrupted => {}
70                Err(e) => return Err(e),
71            }
72        }
73        Ok(())
74    }
75
76    /// Writes a formatted string into this writer, returning any error
77    /// encountered.
78    fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> Result<()> {
79        // NOTE: std's implementation uses an internal method
80        // `as_statically_known_str` to optimize.
81        default_write_fmt(self, args)
82    }
83
84    /// Creates a "by reference" adapter for this instance of `Write`.
85    ///
86    /// The returned adapter also implements `Write` and will simply borrow this
87    /// current writer.
88    fn by_ref(&mut self) -> &mut Self
89    where
90        Self: Sized,
91    {
92        self
93    }
94}