#variant #enums #string #macro-derive #serde-derive #converting #enumscribe

无std enumscribe_derive

用于在枚举和字符串之间转换的派生宏

8个不稳定版本 (3个破坏性更新)

0.4.0 2023年11月19日
0.3.1 2023年10月2日
0.3.0 2023年7月27日
0.2.1 2023年2月8日
0.1.1 2021年5月22日

#60 in #serde-derive

Download history 181/week @ 2024-03-13 99/week @ 2024-03-20 55/week @ 2024-03-27 149/week @ 2024-04-03 55/week @ 2024-04-10 75/week @ 2024-04-17 120/week @ 2024-04-24 57/week @ 2024-05-01 62/week @ 2024-05-08 75/week @ 2024-05-15 85/week @ 2024-05-22 193/week @ 2024-05-29 149/week @ 2024-06-05 174/week @ 2024-06-12 151/week @ 2024-06-19 119/week @ 2024-06-26

每月下载量634
enumscribe中使用

MIT 许可证

72KB
1.5K SLoC

enumscribe

crates.io

该软件包提供用于在简单枚举和字符串之间转换的派生宏。它还包括为简单枚举提供 serde::Serializeserde::Deserialize 的派生宏。

将enumscribe添加到您的项目

添加到您的Cargo.toml文件

[dependencies]
enumscribe = "0.4"

派生宏和 serde 支持默认启用。可以通过设置 default-features = false 来禁用。

还可以单独使用 enumscribe_derive 软件包,而不使用 enumscribe 软件包。但是,这样做意味着您只能派生 serde::Serializeserde::Deserialize

使用方法

您可以从多种不同的特质中派生。 "Scribe" 特质用于将枚举转换为字符串,而 "Unscribe" 特质用于将字符串转换为枚举。

基本用法

use enumscribe::{ScribeStaticStr, TryUnscribe};

#[derive(ScribeStaticStr, TryUnscribe, PartialEq, Eq, Debug)]
enum Airport {
    #[enumscribe(str = "LHR")]
    Heathrow,
    #[enumscribe(str = "LGW")]
    Gatwick,
    #[enumscribe(str = "LTN")]
    Luton,
}

// Convert an Airport to a &'static str
assert_eq!(Airport::Heathrow.scribe(), "LHR");
    
// Convert a &str to a Option<Airport>
assert_eq!(Airport::try_unscribe("LGW"), Some(Airport::Gatwick));

#[enumscribe(str = "...")] 允许我们指定用于表示特定变体的字符串。如果省略,将使用变体的名称。

不区分大小写

可以使用 #[enumscribe(case_insensitive)] 属性使 "Unscribe" 特性对变体执行不区分大小写的匹配。

use enumscribe::TryUnscribe;

#[derive(TryUnscribe, PartialEq, Eq, Debug)]
enum Website {
    #[enumscribe(str = "github.com", case_insensitive)]
    Github,
    #[enumscribe(str = "crates.io", case_insensitive)]
    CratesDotIo,
}

assert_eq!(Website::try_unscribe("GiThUb.CoM"), Some(Website::Github));

相同的属性也可以用在枚举本身上,使所有变体不区分大小写。个别字段可以通过使用 #[enumscribe(case_sensitive)] 来重新启用大小写敏感。

use enumscribe::TryUnscribe;

#[derive(TryUnscribe, PartialEq, Eq, Debug)]
#[enumscribe(case_insensitive)]
enum Website {
    #[enumscribe(str = "github.com")]
    Github,
    #[enumscribe(str = "crates.io")]
    CratesDotIo,
}

assert_eq!(Website::try_unscribe("CrAtEs.Io"), Some(Website::CratesDotIo));

"other" 变体

您还可以有一个存储无法匹配到任何其他变体的字符串的变体。这可以通过使用 #[enumscribe(other)] 属性来完成。该变体应有一个单字段,该字段是 String

use std::borrow::Cow;

use enumscribe::{Unscribe, ScribeCowStr};

#[derive(ScribeCowStr, Unscribe, PartialEq, Eq, Debug)]
enum Website {
    #[enumscribe(str = "github.com", case_insensitive)]
    Github,
    #[enumscribe(str = "crates.io", case_insensitive)]
    CratesDotIo,
    #[enumscribe(other)]
    Other(String),
}

// Note that we don't need to use an Option anymore!
assert_eq!(Website::unscribe("github.com"), Website::Github);

// Unbelievably, websites exist other than github and crates.io
assert_eq!(Website::unscribe("stackoverflow.com"), Website::Other("stackoverflow.com".to_owned()));

// We can't scribe to a &'static str anymore, so we use a Cow<'static, str> instead
assert_eq!(Website::Github.scribe(), Cow::Borrowed::<'static, str>("github.com"));

assert_eq!(Website::Other("owasp.org".to_owned()).scribe(), Cow::Owned::<'static, str>("owasp.org".to_owned()));

忽略变体

如果需要,您可以使用 #[enumscribe(ignore)] 阻止变体被 Scribe 或 Unscribe 特性使用。

但是,这意味着将枚举转换为字符串可能会失败,因此您必须在这种情况下使用 TryScribe 而不是 Scribe。

use enumscribe::TryScribeStaticStr;

#[derive(TryScribeStaticStr, PartialEq, Eq, Debug)]
enum Airport {
    #[enumscribe(str = "LHR")]
    Heathrow,
    #[enumscribe(str = "LGW")]
    Gatwick,
    #[enumscribe(str = "LTN")]
    Luton,
    #[enumscribe(ignore)]
    SecretExtraVariant(i32), // we have to ignore this variant because of the i32 field
}

assert_eq!(Airport::SecretExtraVariant(123).try_scribe(), None);

assert_eq!(Airport::Luton.try_scribe(), Some("LTN"));

Serde

您可以使用相同的语法来推导 serde::Serializeserde::Deserialize

use serde::{Serialize, Deserialize};

use enumscribe::{EnumSerialize, EnumDeserialize};

#[derive(EnumSerialize, EnumDeserialize, PartialEq, Eq, Clone, Copy, Debug)]
enum Airport {
    #[enumscribe(str = "LHR")]
    Heathrow,
    #[enumscribe(str = "LGW")]
    Gatwick,
    #[enumscribe(str = "LTN")]
    Luton,
}

#[derive(Serialize, Deserialize, PartialEq, Eq, Debug)]
struct Flight {
    takeoff: Airport,
    landing: Airport,
}

// There are probably much more economical ways of making this journey
let flight = Flight {
    takeoff: Airport::Heathrow,
    landing: Airport::Gatwick,
};

let flight_json = r#"{"takeoff":"LHR","landing":"LGW"}"#;

assert_eq!(serde_json::to_string(&flight).unwrap(), flight_json.to_owned());

assert_eq!(serde_json::from_str::<Flight>(flight_json).unwrap(), flight);

特质表

以下表格显示了根据您的枚举,您应该推导哪个特质

是否使用了 ignore 是否使用了 other 转换为字符串 从字符串转换
ScribeStaticStr TryUnscribe
ScribeCowStr Unscribe
TryScribeStaticStr TryUnscribe
TryScribeCowStr Unscribe

还有 ScribeStringTryScribeString 特质,它们可以在与 ScribeCowStrTryScribeCowStr 相同的情况下使用。这些特质产生一个 String 而不是 Cow<'static, str>,因此它们将始终执行分配。因此,除非您确实不想使用 Cow 的任何原因,否则您应该优先使用 ScribeCowStr 特质而不是 ScribeString 特质。

依赖项

~1.5MB
~35K SLoC