我有一个有许多价值观的枚举
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
...
Quux = 0xFF
}
Run Code Online (Sandbox Code Playgroud)
有时我想将其中一个值的名称写入流中.我可以得出Debug做
writer.write(format!("I am {:?}", Foo::Quux).as_bytes())
Run Code Online (Sandbox Code Playgroud)
这将输出例如I am Quux.那很好,除了那个
实现这一目标的最佳方法是什么?
Vla*_*eev 38
可能最简单的方法是Display通过调用Debug:
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self)
// or, alternatively:
// fmt::Debug::fmt(self, f)
}
}
Run Code Online (Sandbox Code Playgroud)
然后你可以to_string()用来获得一个String表示:
let s: String = Foo::Quux.to_string();
Run Code Online (Sandbox Code Playgroud)
如果您要打印许多枚举,可以编写一个简单的宏来Display为每个枚举生成上述实现.
不幸的是,在Rust中,反射编程有点困难.例如,没有标准的方法来获取类似C的枚举的所有变体的列表.几乎总是你必须使用自定义编写的宏来抽象样板(或者在crates.io上找到一些东西).如果有人写一个RFC并且它会被接受,将来可能会改变.
由于枚举变量的名称是固定的,你并不需要分配一个String,一个&'static str就够了。宏可以删除样板:
macro_rules! enum_str {
(enum $name:ident {
$($variant:ident = $val:expr),*,
}) => {
enum $name {
$($variant = $val),*
}
impl $name {
fn name(&self) -> &'static str {
match self {
$($name::$variant => stringify!($variant)),*
}
}
}
};
}
enum_str! {
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
}
fn main() {
assert_eq!(Foo::Baz.name(), "Baz");
}
Run Code Online (Sandbox Code Playgroud)
更好的是,您可以使用strum_macros这样的板条箱派生这些。
在strum 0.10中,您可以使用AsStaticRef/ AsStaticStr来执行完全相同的代码:
extern crate strum; // 0.10.0
#[macro_use]
extern crate strum_macros; // 0.10.0
use strum::AsStaticRef;
#[derive(AsStaticStr)]
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
fn main() {
assert_eq!(Foo::Baz.as_static(), "Baz");
}
Run Code Online (Sandbox Code Playgroud)
在strum 0.9中,字符串切片的生存期在这种情况下不是'static:
#[macro_use]
extern crate strum_macros; // 0.9.0
#[derive(AsRefStr)]
enum Foo {
Bar = 0x00,
Baz = 0x01,
Qux = 0x02,
//...
Quux = 0xFF,
}
fn main() {
assert_eq!(Foo::Baz.as_ref(), "Baz");
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
12859 次 |
| 最近记录: |