#enums #derive #macro #custom-derive

no-std enum_derive

本软件包提供了用于为枚举派生额外功能的宏

4 个版本

使用旧的 Rust 2015

0.1.7 2016 年 8 月 3 日
0.1.3 2015 年 12 月 1 日
0.1.2 2015 年 9 月 16 日
0.1.1 2015 年 8 月 16 日

1802Rust 模式

Download history 2366/week @ 2024-03-14 2839/week @ 2024-03-21 2361/week @ 2024-03-28 2236/week @ 2024-04-04 1935/week @ 2024-04-11 2053/week @ 2024-04-18 2404/week @ 2024-04-25 1909/week @ 2024-05-02 2605/week @ 2024-05-09 1992/week @ 2024-05-16 1670/week @ 2024-05-23 2261/week @ 2024-05-30 2967/week @ 2024-06-06 2581/week @ 2024-06-13 2983/week @ 2024-06-20 2305/week @ 2024-06-27

11,471 每月下载量
用于 31 个软件包(其中 13 个直接使用)

MIT/Apache

30KB
678

本软件包提供了一些宏,用于派生一些针对单元枚举(即,变体没有有效负载的枚举)的有用方法。

所有这些宏都是为与 custom_derive 软件包一起使用而设计的,尽管它们可以在不依赖它的前提下使用。

注意:还可以查看 conv 软件包提供的 TryFrom! 宏,用于从整数值派生创建枚举值的功能。

示例

派生迭代器,返回枚举的所有变体。

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate enum_derive;

custom_derive! {
#[derive(Debug, PartialEq, Eq,
IterVariants(CandyVariants), IterVariantNames(CandyVariantNames))]
pub enum Candy { Musk, FruitRock, BoPeeps, LemonSherbert }
}

let vars: CandyVariants = Candy::iter_variants();
let names: CandyVariantNames = Candy::iter_variant_names();
assert_eq!(&*vars.zip(names).collect::<Vec<_>>(), &[
(Candy::Musk, "Musk"),
(Candy::FruitRock, "FruitRock"),
(Candy::BoPeeps, "BoPeeps"),
(Candy::LemonSherbert, "LemonSherbert"),
]);

或者,派生 next_variantprev_variant 方法。

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate enum_derive;

use Hanagami::*;

custom_derive! {
#[derive(Debug, PartialEq, Eq, NextVariant, PrevVariant)]
pub enum Hanagami { Sakigami, Hasugami, Tsutagami }
}

assert_eq!(Sakigami.next_variant(), Some(Hasugami));
assert_eq!(Hasugami.next_variant(), Some(Tsutagami));
assert_eq!(Tsutagami.next_variant(), None);

assert_eq!(Sakigami.prev_variant(), None);
assert_eq!(Hasugami.prev_variant(), Some(Sakigami));
assert_eq!(Tsutagami.prev_variant(), Some(Hasugami));

概述

本软件包提供宏以派生以下单元变体枚举的方法

  • EnumDisplay 派生 Display,输出变体的名称。注意,对于单元变体,这与派生的 Debug 实现的行为相同。
  • EnumFromStr 派生 FromStr,允许使用 str::parse。它需要变体名称的精确匹配。
  • IterVariants 派生 iter_variants(),返回一个迭代器,按词典顺序遍历枚举的变体。
  • IterVariantNames 派生 iter_variant_names(),返回一个迭代器,按词典顺序遍历枚举变体的字符串名称。
  • NextVariant 派生 next_variant(&self),返回下一个变体,或者当调用最后一个时返回 None
  • PrevVariant 继承了 prev_variant(&self),它返回前一个变体,或者在第一次调用时返回 None
  • EnumFromInner 为每个变体的有效负载继承 From<T>,假设所有变体都是一元。
  • EnumInnerAsTrait 继承了一个方法,用于返回一个指向内部值的借用指针,并将其转换为特质对象。

这两个 IterVariant* 宏都接受一个继承形式。以 IterVariants 为例,它必须如下调用

custom_derive! {
#[derive(IterVariants(GetVariants))]
pub enum Get { Up, Down, AllAround }
}

参数是生成的迭代器类型的名称。这两个宏都不强制命名要求,除了明显的:名称不能与其他任何类型冲突。

EnumInnerAsTrait 接受一个继承形式,指定要继承的方法的名称、借用是否可变以及感兴趣的特质。例如

custom_derive! {
#[derive(EnumInnerAsTrait(pub as_display -> &std::fmt::Display))]
enum Value {
U32(u32),
U64(u64),
}
}

let s = format!("{}", Value::U64(42).as_display());
assert_eq!(&s[..], "42");

其他宏不接受任何参数。

生成的方法和迭代器类型如果是公有的,则将是公开的;否则,它们将是私有的。

使用 custom_derive! 之外的方法

尽管设计为与 custom_derive! 一起使用,但这个crate中的所有宏都可以不使用它来使用。以下

custom_derive! {
#[derive(Copy, Clone, Debug, IterVariants(Vars))]
enum ItAintRight { BabeNo, NoNo, BoyBoy }
}

也可以写成这样

#[derive(Copy, Clone, Debug)]
enum ItAintRight { BabeNo, NoNo, BoyBoy }

IterVariants! { (Vars) enum ItAintRight { BabeNo, NoNo, BoyBoy } }

其他示例

这显示了如何使用 DisplayFromStr 来执行枚举的字符串往返。

#[macro_use] extern crate custom_derive;
#[macro_use] extern crate enum_derive;

custom_derive! {
#[derive(Debug, PartialEq, EnumDisplay, EnumFromStr)]
pub enum TrollDigit { One, Two, Three, Many, Lots }
}

fn to_troll(mut n: u32) -> String {
use std::fmt::Write;
let mut s = String::new();

if n == 0 {
panic!("I dun' see nuffin'; how's I s'posed to count it?!");
}

while n > 0 {
let (del, dig) = match n {
n if n >= 16 => (16, TrollDigit::Lots),
n if n >= 4 => (4, TrollDigit::Many),
n if n >= 3 => (3, TrollDigit::Three),
n if n >= 2 => (2, TrollDigit::Two),
_ => (1, TrollDigit::One),
};
n -= del;
if s.len() > 0 { s.push_str(" "); }
write!(&mut s, "{}", dig).unwrap();
}

s
}

fn from_troll(s: &str) -> Result<u32, enum_derive::ParseEnumError> {
let mut n = 0;
for word in s.split_whitespace() {
n += match try!(word.parse()) {
TrollDigit::One => 1,
TrollDigit::Two => 2,
TrollDigit::Three => 3,
TrollDigit::Many => 4,
TrollDigit::Lots => 16,
};
}
if n == 0 {
Err(enum_derive::ParseEnumError)
} else {
Ok(n)
}
}

let number = 42;
let troll_number = to_troll(number);
assert_eq!(troll_number, "Lots Lots Many Many Two");
assert_eq!(from_troll(&troll_number), Ok(number));

无运行时依赖