[英]Can I convert a string to enum without macros in Rust?
例如,如果我有这样的代码:
enum Foo {
Bar,
Baz,
Bat,
Quux
}
impl Foo {
from(input: &str) -> Foo {
Foo::input
}
}
这显然会失败,因为input
不是 Foo 的方法。 我可以手动输入:
from(input: &str) -> Foo {
match(input) {
"Bar" => Foo::Bar,
// and so on...
}
}
但我没有得到自动便利。
为了这个特定目的,Java 似乎在枚举上有一个字符串查找功能。
是否可以在不编写自己的宏或从板条箱中导入宏的情况下获得它?
编辑:答案是否定的。 Rust 不提供反射,通常使用#[derive]
来处理这类任务。
您可以使用板条箱enum_derive
和custom_derive
来做您想做的事。
这是一个例子:
#[macro_use]
extern crate custom_derive;
#[macro_use]
extern crate enum_derive;
custom_derive! {
#[derive(Debug, EnumFromStr)]
enum Foo {
Bar,
Baz,
Bat,
Quux
}
}
fn main() {
let variable: Foo = "Bar".parse().unwrap();
println!("{:?}", variable);
}
自定义EnumFromStr
的derive
允许您使用parse
方法来获取Foo
。
你应该实现std::str::FromStr特性。
use std::str::FromStr;
#[derive(Debug, PartialEq)]
enum Foo {
Bar,
Baz,
Bat,
Quux,
}
impl FromStr for Foo {
type Err = ();
fn from_str(input: &str) -> Result<Foo, Self::Err> {
match input {
"Bar" => Ok(Foo::Bar),
"Baz" => Ok(Foo::Baz),
"Bat" => Ok(Foo::Bat),
"Quux" => Ok(Foo::Quux),
_ => Err(()),
}
}
}
fn main() {
// Use it like this
let f = Foo::from_str("Baz").unwrap();
assert_eq!(f, Foo::Baz);
}
代码生成(又名自动便利)和反射通常需要付出代价。 在实践中,您不太可能最终得到多个枚举变体。
在操场上奔跑
与其他答案相同的免责声明:“没有宏”是不可能的。
扩展最高投票的答案。 如该线程中所述, custom_derive
+ enum_derive
的组合有些过时。 现代 Rust 不再需要基于custom_derive
的解决方案。
一个现代的替代品是strum
。 用法可能如下所示:
use strum_macros::EnumString;
use std::str::FromStr;
#[derive(EnumString)]
enum Foo {
Bar,
Baz,
Bat,
Quux
}
fn example_usage(input: &str) -> Foo {
Foo::from_str(input).unwrap()
}
注意:您同时需要strum
和strum_macros
在Cargo.toml
。
strum
还为字符串表示提供了一些很好的灵活性。 从文档:
请注意,默认情况下
FromStr
的实现仅匹配变体的名称。 有一个选项可以通过#[strum(serialize_all = "snake_case")]
类型属性匹配不同的大小写转换。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.