Buffering isn't free, and depending on your application, buffering can be a net cost, not a win. Given that there's no "right" answer, Rust leaves you to pick the right answer.
Fundamentally, buffering costs you memory and code complexity (the code doing the buffering) in return for reducing the number of accesses you have to make to the underlying stream. It does this on the read side by making big read requests to fill the buffer, and then copying data from the buffer instead of making more read requests until the buffer is empty, and on the write side by copying your data into the buffer, then writing the buffer out when it's full or it's flushed.
If you're always working in large chunks, or if you need to flush after every operation so that the data gets out, you don't benefit from buffering, but you do pay a cost for having the buffer in place. For example, if you're implementing something like std::io::copy
, buffering is going to cost you, but you're working in large chunks in as far as possible, so all reads are as big as or bigger than the read buffer (⇒ a read buffer doesn't help), and all writes are either too big to buffer, or flushed immediately after writing (⇒ a write buffer doesn't help).
Similar can apply even with very small chunks; "what is your name?" is a short string to write, but having written it out, if I'm going to wait for the user to supply input, I'm going to want to flush immediately. That makes the buffer useless if I did the write in one call, since I'm then immediately paying the price of flushing the buffer - whereas with an unbuffered write, I only need make one write call and it's done.
So, given that there are cases where I lose out if the write or read is buffered, the default can't be buffered, since that makes everyone pay the cost of buffering, even when it's not needed.
However, against that, there are plenty of cases where buffering does help; if you're reading byte-by-byte, for example, it's cheaper to do a single big read into a buffer, and then copy bytes out of it than to do reads of a single byte at a time from the underlying source. Similarly, if you're writing 1 to 16 byte chunks from calling to_le_bytes
on an integer or floating point number, having the buffer turn that into a small number of big writes is helpful.
So, there needs to be an easy way to add buffering if you know it's needed - but that needs to be used only where appropriate, since otherwise you pay the cost of multiple buffers in a stack, rather than just a single buffer.