【问题标题】:Enum to &str / &str to Enum枚举到 &str / &str 到枚举
【发布时间】:2021-09-22 23:38:31
【问题描述】:

想知道是否有将Enum 转换为&str 并返回的“正确”方式。

我要解决的问题:

clap crate 中,args/子命令由&strs 定义和标识。 (我假设没有完全利用类型检查器。)我想将 Command Enum 传递给我的应用程序,而不是 &str ,这将由类型检查器和也让我免于在各处输入(打字?)字符串。

这是我通过搜索 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");
}

这是一个工作场所: 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();

它似乎有效,但我不确定我是否遗漏了什么/更大的图景。

相关:

谢谢!

【问题讨论】:

  • FWIW,structopt crate 正好处理这种情况。但无论如何,这是一个好问题!不,我认为你没有遗漏任何东西。
  • 是的!我看起来超级酷,我还记得偶然发现claps beta documentation 似乎使用了类似的语法......但是,是的,只是好奇其他人如何在这个特定情况之外处理这个问题。 @纳撒尼尔福特
  • serializable_enumenum_from_str 板条箱可以在这里提供帮助。
  • 其实有a lot of crates可以做到的。
  • @Jmb 谢谢!是的,我还不够精通 rust,不知道什么时候拿一个箱子,或者什么时候只用std 自己实现它。

标签: rust enums


【解决方案1】:

strum crate 可以为您节省一些工作。使用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");
}

【讨论】:

  • 这看起来是一个非常干净的解决方案。我从可用的 crate 数量和对这个问题的回答中假设,使用我的实现和使用 crate 会比较相似,只是由用户来选择。
  • 你是对的@se432
猜你喜欢
  • 2018-03-31
  • 1970-01-01
  • 2020-08-17
  • 1970-01-01
  • 2019-08-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多