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