I want to write a function that produces some text, like so:
fn produce_stuff(/* ??? */) -> Result<()> {
write!(...);
write!(...);
write!(...);
...
}
I want to be able to use this function in two contexts:
produce_text(io.stdout()).Display — something like this:struct Foo { ... }
impl Display for Foo {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
...
produce_text(f);
...
}
}
It seems like each of these use cases would require a different signature for produce_text. For #1, the function would need to take something that implements std::io::Write, and for #2 it would need to take a std::fmt::Formatter.
I suppose I could write it as a macro instead of as a function (similar to how write! is a macro that works both in both contexts), but it somehow feels wrong to use a macro for this.
You just have to implement Display.
When your Foo implements Display, you can use it with any implementation of Write, including io::Stdout:
use std::{
io::{self, Write},
fmt,
};
struct Foo {
field: u16,
}
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Foo({})", self.field)
}
}
fn main() {
write!(io::stdout(), "{}", Foo{field: 3}).unwrap();
}
You don't have to write your own macro; just use write!. This should not feel wrong, it's the normal way.
There's no runtime cost related to the "{}" argument: it's parsed at compile time (in a compiler built-in), which makes the write!(w, "{}", displayable) call efficient.
playground
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With