#枚举 #常量 #变体 #表格 #常量

table_enum

一个方便的Rust宏,用于创建具有关联常量数据的枚举(注意:这与普通的Rust枚举不同,普通Rust枚举实际上是标签联合体)

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 次下载

MIT 许可证

6KB

table-enum

Icon

一个方便的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