Description
Currently, the behavior of BufWriter
reaching a full buffer is that it calls the equivalent of inner.write
, sending its buffered data to the wrapped writer, but not necessarily sending it all the way to the final sink. Conversely, LineWriter
calls flush
every time it hits a newline, which means it sends each written line to the final sink.
For example, suppose you had LineWriter<BufWriter<Stdout>>
. Each time a line is written to the LineWriter
, it's written all the way to Stdout
, regardless of the buffering of that BufWriter
in the middle.
It appears that the only reason this is the case is that, for simplicity, LineWriter
is implemented as a wrapper around BufWriter
. Because BufWriter
doesn't expose direct control of how the buffer is written, the only way for LineWriter
to cause the line to be written to the inner device is by calling BufWriter::flush
.
My proposal, therefore, is to move the line-writing logic into methods on BufWriter
(for instance, BufWriter::write_line_buffered
), or into free functions. These methods would by simplified by having the needs_flush
bool; they would instead return a bool
with their Ok Result if a write succeeded but the flush failed. This design means that the logic may work with the buffer directly (through the write
and flush_buf
methods). Additionally- and this was the issue that motivated me to write this report in the first place- this would streamline the implementation of #60673, which calls for a way for Stdout
to be put in block-buffering mode instead of line-buffering, either through a runtime switch, or tty
detection. Currently, the only way to implement this without substantial logic duplication is something like enum { LineWriter, BufWriter }
, which has the disadvantage of not being switchable after creation.
This would be a change to the observable behavior, so I'm filing it as an issue here for discussion before implementing it.