#枚举 #标签 #c-like #tagged #判别式 #过程宏

无 std enum-tag-macro

enum-tag 包提供过程宏实现。

3 个版本 (破坏性更新)

0.3.0 2023 年 3 月 28 日
0.2.0 2023 年 3 月 24 日
0.1.0 2023 年 3 月 23 日

6#c-like

Download history 18/week @ 2024-03-14 29/week @ 2024-03-21 45/week @ 2024-03-28 43/week @ 2024-04-04 5/week @ 2024-04-11 10/week @ 2024-04-18 35/week @ 2024-04-25 1121/week @ 2024-05-02 5899/week @ 2024-05-09 4308/week @ 2024-05-16 6725/week @ 2024-05-23 5046/week @ 2024-05-30 873/week @ 2024-06-06 519/week @ 2024-06-13 832/week @ 2024-06-20 358/week @ 2024-06-27

每月 2,832 次下载
用于 enum-tag

MIT 许可证

11KB
82

[2]: https://github.com/Robbepop/enum-tag/actions/workflows/rust.yml [4]: https://docs.rs/enum-tag [6]: https://crates.io/crates/enum-tag

持续集成 文档 Crates.io
[ci][2] [docs][4] [crates][6]

#[derive(EnumTag)]

此包提供过程宏,以派生给定的 Rust enum#derive(EnumTag) 特性。此过程宏仅适用于 Rust enum 类型,并生成以下内容:

  • 一个与输入 Rust enum 有相同变体但不含所有关联数据的类似 C 的 enum 类型。
  • 为 Rust enum 派生 EnumTag 特性的实现。

派生的 EnumTag 特性使得可以创建生成的类似 C 的 enum 类型的实例,并通过 <RustEnum as EnumTag>::Tag 链接到其定义。

何时使用此功能?

这对于拥有独特的枚举标签类型的crate来说非常有用,同时它还托管了带有大量变体的Rust 枚举类型,这使得维护这两种枚举类型之间的镜像变得负担重重。

这个crate的动机是一个Wasm解释器,它将指令表示为枚举,但同时也希望访问指令的指令码而不涉及数据。在这个例子中,指令码是指令的枚举标签。

示例

use ::enum_tag::EnumTag;

#[derive(EnumTag)]
#[repr(u8)] // Rust needs this for `B = 42`
enum Foo {
    A,
    B = 42,
    C(i32),
    D(i32, i64),
    E { a: i32 },
    F { a: i32, b: i64 },
}

/// This is how we can access the generated C-like enum type and name it.
type FooTag = <Foo as EnumTag>::Tag;

assert_eq!(FooTag::A, Foo::A.tag());
assert_eq!(FooTag::B, Foo::B.tag());
assert_eq!(FooTag::C, Foo::C(1).tag());
assert_eq!(FooTag::D, Foo::D(2, 3).tag());
assert_eq!(FooTag::E, Foo::E { a: 4 }.tag());
assert_eq!(FooTag::F, Foo::F { a: 5, b: 6 }.tag());

assert_eq!(FooTag::B as u8, 42);

上面的#[derive(EnumTag)]生成以下Rust代码

const _: () = {
    #[derive(
        ::core::fmt::Debug,
        ::core::clone::Clone,
        ::core::marker::Copy,
        ::core::cmp::PartialEq,
        ::core::cmp::Eq,
        ::core::cmp::PartialOrd,
        ::core::cmp::Ord,
        ::core::hash::Hash,
    )]
    pub enum FooTag {
        A,
        B = 42,
        C,
        D,
        E,
        F,
    }

    impl ::enum_tag::EnumTag for Foo {
        type Tag = FooTag;

        fn tag(&self) -> <Self as ::enum_tag::EnumTag>::Tag {
            match self {
                Self::A { .. } => <Self as ::enum_tag::EnumTag>::Tag::A,
                Self::B { .. } => <Self as ::enum_tag::EnumTag>::Tag::B,
                Self::C { .. } => <Self as ::enum_tag::EnumTag>::Tag::C,
                Self::D { .. } => <Self as ::enum_tag::EnumTag>::Tag::D,
                Self::E { .. } => <Self as ::enum_tag::EnumTag>::Tag::E,
                Self::F { .. } => <Self as ::enum_tag::EnumTag>::Tag::F,
            }
        }
    }
};

依赖关系

~290–750KB
~18K SLoC