-
Notifications
You must be signed in to change notification settings - Fork 14k
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.