5个不稳定版本
0.3.0 | 2024年7月4日 |
---|---|
0.2.0 | 2023年11月12日 |
0.1.2 | 2023年7月28日 |
0.1.1 | 2023年7月28日 |
0.1.0 | 2023年7月28日 |
#605 in Rust模式
每月 23 次下载
6KB
table-enum
一个方便的Rust宏,用于创建具有关联常量数据的枚举。它允许您将常量值关联到枚举变体,类似于Java中的枚举,或者C中常用的X宏。
只有枚举标签会被传递,数据通过生成的const fn函数访问,这些函数将枚举标签与相关数据匹配。
这与Rust中通常使用的枚举不同,Rust中的枚举实际上是标签联合体。(也称为计算机科学理论中的变体类型或求和类型)。
何时使用此功能?
非标签联合体枚举非常有用的例子是编译器或解释器开发。例如
use table_enum::table_enum;
table_enum! {
enum BinaryOp(#[constructor] text: &'static str, precedence: i32, #[default] right_assoc: bool) {
Add("+", 10, _),
Sub("-", 10, _),
Mul("*", 20, _),
Div("/", 20, _),
Pow("**", 30, true),
...
}
}
[^1]: 我真希望Rust和Swift没有将他们的标签联合体称为枚举。对我来说,枚举应该像这个宏中一样使用。标签联合体应该是一种联合体。
它是如何工作的?
上面的例子展开成以下代码
enum BinaryOp {
Add,
Sub,
Mul,
Div,
Pow,
...
}
impl BinaryOp {
const fn text(&self) -> &'static str {
match self {
BinaryOp::Add => "+",
BinaryOp::Sub => "-",
BinaryOp::Mul => "*",
BinaryOp::Div => "/",
BinaryOp::Pow => "**",
...
}
}
pub fn new(text: &'static str) -> Option<Self> {
match text {
"+" => Some(BinaryOp::Add),
"-" => Some(BinaryOp::Sub),
"*" => Some(BinaryOp::Mul),
"/" => Some(BinaryOp::Div),
"**" => Some(BinaryOp::Pow),
...
_ => None
}
}
const fn precedence(&self) -> i32 {
match self {
BinaryOp::Add => 10,
BinaryOp::Sub => 10,
BinaryOp::Mul => 20,
BinaryOp::Div => 20,
BinaryOp::Pow => 30,
...
}
}
// cannot be const because Default::default() is not const
fn right_assoc(&self) -> bool {
match self {
BinaryOp::Add => bool::default(),
BinaryOp::Sub => bool::default(),
BinaryOp::Mul => bool::default(),
BinaryOp::Div => bool::default(),
BinaryOp::Pow => true,
...
}
}
}
注意,最多只能有一个字段具有#[constructor]
属性。如果一个字段具有#[constructor]
属性,则该字段必须为每个枚举标签具有不同的值。
变更日志
- 0.3.0: 添加了
#[constructor]
属性。 - 0.2.0: 向枚举字段声明中添加了
#[option]
和#[default]
属性,请参阅文档以获取更多信息。 - 0.1.0: 第一个版本
其他Crates
- enum-assoc:功能更强大但使用不太方便。
- const-table:类似的想法,但作为一个属性宏。说实话,在语法上这是一个更好的解决方案。不幸的是,它使用结构体数组的布局而不是数组结构体。
依赖关系
~320–780KB
~18K SLoC