有什么方法可以编写可以输出到std :: io :: Write或std :: fmt :: Formatter的函数?

Wil*_*ill 5 rust

我想编写一个生成一些文本的函数,如下所示:

fn produce_stuff(/* ??? */) -> Result<()> {
    write!(...);
    write!(...);
    write!(...);
    ...
}
Run Code Online (Sandbox Code Playgroud)

我希望能够在两种情况下使用此功能:

  1. 使用它输出到IO编写器-之类的produce_text(io.stdout())
  2. 在实现时将其用作辅助函数,Display如下所示:
struct Foo { ... }
impl Display for Foo {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        ...
        produce_text(f);
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎这些用例中的每个用例都需要为签名不同produce_text。对于#1,该函数将需要采用一些已实现的东西,对于#2,该函数将需要std::io::Write采用一个std::fmt::Formatter

我想我可以将它写为一个宏而不是一个函数(类似于write!在两种情况下都可以工作的宏),但是为此使用宏有些不妥。

Den*_*ret 5

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();
}
Run Code Online (Sandbox Code Playgroud)

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