Description
Proposal
Problem statement
There is no easy way to use fmt::Write
to write bytes to an io stream.
Motivation, use-cases
If you know the format data you'll be creating must always be valid utf8, then you should use the fmt::Write
trait. Unfortunately, it is harder than necessary to then lower that data down into a byte stream.
This basically comes down to being able to interchangeably use a String
buffer or a io::stdout()
buffer (for example). You could argue that you should use a Vec<u8>
and then convert it to a string, but now you've lost the type safety of guaranteed utf8.
Solution sketches
The big open question is error handling, but I don't believe this needs to be addressed while the feature is unstable.
API:
struct FmtWriteAdapter<'a, W: Write + ?Sized> { ... }
impl FmtWriteAdapter {
pub fn err(&self) -> &Option<Error>
pub fn mut_err(&mut self) -> &mut Option<Error>
}
impl<W: Write + ?Sized> fmt::Write for FmtWriteAdapter<'_, W>
impl io::Write {
fn fmt_adapter(&mut self) -> FmtWriteAdapter<'_, Self> where Self: Sized
}
Usage:
let mut output1 = String::new();
let mut output2 = io::stdout();
my_common_writer(&mut output1).unwrap();
my_common_writer(&mut output2.fmt_adapter()).unwrap();
fn my_common_writer(output: &mut impl fmt::Write) -> fmt::Result {
writeln!(output, "Hello World!")
}
Links and related work
Existing issue: rust-lang/rust#77733
Note: the other direction (i.e. writing through an io stream to a format stream) does not make sense because the data does not have to be utf8. Even it was and error handling could be taken care of, the window of data the io stream is currently viewing may not be aligned to valid utf8 data, meaning the data may actually be utf8 but the order in which the writes appeared made the data invalid.