我可以在Rust中将字符串转换为枚举而不使用宏吗?

bri*_*tar 7 string macros enums parsing rust

例如,如果我有以下代码:

enum Foo {
    Bar,
    Baz,
    Bat,
    Quux
}

impl Foo {
    from(input: &str) -> Foo {
        Foo::input
    }
}
Run Code Online (Sandbox Code Playgroud)

这显然会失败,因为input它不是Foo的方法.我可以手动输入:

from(input: &str) -> Foo {
    match(input) {
        "Bar" => Foo::Bar,
        // and so on...
    }
}
Run Code Online (Sandbox Code Playgroud)

但我没有获得自动便利.

看起来Java 在枚举上有一个字符串查找功能,用于此特定目的.

是不是可以在不编写自己的宏或从箱子中导入宏的情况下获得这个?

Pie*_*Pah 25

你应该实现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);
}
Run Code Online (Sandbox Code Playgroud)

代码生成(又名自动便利)和反射通常需要付出代价。在实践中,您不太可能最终得到多个枚举变体。

操场上奔跑

  • 有没有什么奇特的方法可以让编译器检查输出列表是否详尽而无需任何运行时成本? (2认同)

blu*_*e10 13

与其他答案相同的免责声明:“没有宏”是不可能的。

扩展最高投票的答案。正如在此线程中所指出的,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()
}
Run Code Online (Sandbox Code Playgroud)

注意:您同时需要strumstrum_macros你的Cargo.toml

strum还为字符串表示提供了一些很好的灵活性。从文档

请注意,FromStr默认情况下的实现仅匹配变体的名称。有一个选项可以通过#[strum(serialize_all = "snake_case")]type 属性匹配不同的大小写转换。


ant*_*oyo 12

您可以使用板条箱enum_derivecustom_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);
}
Run Code Online (Sandbox Code Playgroud)

derive自定义的EnumFromStr允许您使用的parse方法来获取Foo.

  • 做完了 哎呀,接下来你们会问这个问题的类型注解... (2认同)