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

时间:2019-07-31 01:05:55

标签: rust

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

fn produce_stuff(/* ??? */) -> Result<()> {
    write!(...);
    write!(...);
    write!(...);
    ...
}

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

  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);
        ...
    }
}

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

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

1 个答案:

答案 0 :(得分:5)

您只需要实现Display

Foo实现Display时,您可以将其与Write的任何实现一起使用,包括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();
}

您不必编写自己的宏;只需使用write!。这应该不会错,这是正常的方法。

"{}"参数无关的运行时成本:它是在编译时(在内置的编译器中)进行解析的,这使write!(w, "{}", displayable)的调用效率很高。

playground