Skip to main content

ax_io/buffered/linewriter/
mod.rs

1mod shim;
2
3use core::fmt;
4
5use self::shim::LineWriterShim;
6use crate::{BufWriter, IntoInnerError, IoBufMut, Result, Write};
7/// The [`BufWriter`] struct wraps a writer and buffers its output.
8/// But it only does this batched write when it goes out of scope, or when the
9/// internal buffer is full. Sometimes, you'd prefer to write each line as it's
10/// completed, rather than the entire buffer at once. Enter `LineWriter`. It
11/// does exactly that.
12///
13/// Like [`BufWriter`], a `LineWriter`’s buffer will also be flushed when the
14/// `LineWriter` goes out of scope or when its internal buffer is full.
15///
16/// If there's still a partial line in the buffer when the `LineWriter` is
17/// dropped, it will flush those contents.
18///
19/// See [`std::io::LineWriter`] for more details.
20pub struct LineWriter<W: ?Sized + Write> {
21    inner: BufWriter<W>,
22}
23
24impl<W: Write> LineWriter<W> {
25    /// Creates a new `LineWriter`.
26    pub fn new(inner: W) -> LineWriter<W> {
27        LineWriter {
28            inner: BufWriter::new(inner),
29        }
30    }
31
32    /// Creates a new `LineWriter` with at least the specified capacity for the
33    /// internal buffer.
34    #[cfg(feature = "alloc")]
35    pub fn with_capacity(capacity: usize, inner: W) -> LineWriter<W> {
36        LineWriter {
37            inner: BufWriter::with_capacity(capacity, inner),
38        }
39    }
40
41    /// Unwraps this `LineWriter`, returning the underlying writer.
42    ///
43    /// The internal buffer is written out before returning the writer.
44    ///
45    /// # Errors
46    ///
47    /// An [`Err`] will be returned if an error occurs while flushing the buffer.
48    #[cfg_attr(not(feature = "alloc"), allow(clippy::result_large_err))]
49    pub fn into_inner(self) -> core::result::Result<W, IntoInnerError<LineWriter<W>>> {
50        self.inner
51            .into_inner()
52            .map_err(|err| err.new_wrapped(|inner| LineWriter { inner }))
53    }
54}
55
56impl<W: ?Sized + Write> LineWriter<W> {
57    /// Gets a reference to the underlying writer.
58    pub fn get_ref(&self) -> &W {
59        self.inner.get_ref()
60    }
61
62    /// Gets a mutable reference to the underlying writer.
63    ///
64    /// Caution must be taken when calling methods on the mutable reference
65    /// returned as extra writes could corrupt the output stream.
66    pub fn get_mut(&mut self) -> &mut W {
67        self.inner.get_mut()
68    }
69}
70
71impl<W: ?Sized + Write> Write for LineWriter<W> {
72    fn write(&mut self, buf: &[u8]) -> Result<usize> {
73        LineWriterShim::new(&mut self.inner).write(buf)
74    }
75
76    fn flush(&mut self) -> Result<()> {
77        self.inner.flush()
78    }
79
80    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
81        LineWriterShim::new(&mut self.inner).write_all(buf)
82    }
83
84    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
85        LineWriterShim::new(&mut self.inner).write_fmt(fmt)
86    }
87}
88
89impl<W: ?Sized + Write + fmt::Debug> fmt::Debug for LineWriter<W> {
90    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
91        fmt.debug_struct("LineWriter")
92            .field("writer", &self.get_ref())
93            .field(
94                "buffer",
95                &format_args!("{}/{}", self.inner.buffer().len(), self.inner.capacity()),
96            )
97            .finish_non_exhaustive()
98    }
99}
100
101impl<W: ?Sized + Write + IoBufMut> IoBufMut for LineWriter<W> {
102    #[inline]
103    fn remaining_mut(&self) -> usize {
104        self.inner.remaining_mut()
105    }
106}