枚举到 &str / &str 到枚举

tna*_*ahs 4 enums rust

想知道是否有一种“正确”的方法将 an 转换Enum为 a&str并返回。

我试图解决的问题:

clapcrate 中,args/子命令由&strs 定义和标识。(我假设没有完全利用类型检查器。)我想将 a 传递Command Enum给我的应用程序,而不是&str由类型检查器验证的 a ,并且还可以使我免于打字(打字错误) ?)到处都是字符串。

这是我通过搜索 StackOverflow 得出的结论std

use std::str::FromStr;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Command {
    EatCake,
    MakeCake,
}

impl FromStr for Command {
    type Err = ();

    fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
        match s.to_ascii_lowercase().as_str() {
            "eat-cake" => Ok(Self::EatCake),
            "make-cake" => Ok(Self::MakeCake),
            _ => Err(()),
        }
    }
}

impl<'a> From<Command> for &'a str {
    fn from(c: Command) -> Self {
        match c {
            Command::EatCake => "eat-cake",
            Command::MakeCake => "make-cake",
        }
    }
}

fn main() {
    let command_from_str: Command = "eat-cake".to_owned().parse().unwrap();
    let str_from_command: &str = command_from_str.into();

    assert_eq!(command_from_str, Command::EatCake);
    assert_eq!(str_from_command, "eat-cake");
}
Run Code Online (Sandbox Code Playgroud)

这是一个工作游乐场: https://play.rust-lang.org/? version=stable&mode=debug&edition=2018&gist=b5e9ac450fd6a79b855306e96d4707fa

这是我正在运行的内容的删节版本clap

let matches = App::new("cake")
    .setting(AppSettings::SubcommandRequiredElseHelp)
    // ...
    .subcommand(
        SubCommand::with_name(Command::MakeCake.into())
            // ...
    )
    .subcommand(
        SubCommand::with_name(Command::EatCake.into())
            // ...
    )
    .get_matches();
Run Code Online (Sandbox Code Playgroud)

它似乎有效,但我不确定我是否错过了一些东西/更大的图景。

有关的:

谢谢!

Tod*_*odd 8

弹奏箱可以为您节省一些工作。使用strum我能够得到简单的main()工作,无需任何额外的From实现。

use strum_macros::{Display, EnumString, IntoStaticStr};

#[derive(Debug, Clone, Copy, PartialEq)]
#[derive(Display, EnumString, IntoStaticStr)]  // strum macros.
pub enum Command {
    #[strum(serialize = "eat-cake")]
    EatCake,
    
    #[strum(serialize = "make-cake")]
    MakeCake,
}
fn main() {
    let command_from_str: Command = "eat-cake".to_owned().parse().unwrap();
    let str_from_command: &str    = command_from_str.into();

    assert_eq!(command_from_str, Command::EatCake);
    assert_eq!(str_from_command, "eat-cake");
}
Run Code Online (Sandbox Code Playgroud)