#枚举 #标签 #标记 #判别符 #C样式 #过程宏

无需std enum-tag

用于生成枚举判别类型的过程宏。

3个版本 (破坏性更新)

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

1172数据结构

Download history 14/week @ 2024-03-14 20/week @ 2024-03-21 36/week @ 2024-03-28 39/week @ 2024-04-04 28/week @ 2024-04-25 1118/week @ 2024-05-02 5889/week @ 2024-05-09 4300/week @ 2024-05-16 6719/week @ 2024-05-23 5041/week @ 2024-05-30 873/week @ 2024-06-06 516/week @ 2024-06-13 825/week @ 2024-06-20 357/week @ 2024-06-27

每月下载量 2,820

MIT 许可证

7KB

[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)]

此crate提供了一个过程宏,用于为给定的Rust enum推导EnumTag特质。仅当Rust enum类型上使用#derive(EnumTag)过程宏时,它才有效,并生成

  • 一个与输入Rust enum具有相同变体的C样式enum类型,但不包含所有相关数据。
  • 为Rust enum推导的EnumTag特质实现

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

何时使用此功能?

这对于那些从具有独特enum标签类型的crate中获益,同时又要托管具有许多变体的Rust enum类型,这使得在两种enum类型之间维护镜像变得负担沉重的情况非常有用。

此crate的动机是一个Wasm解释器,它将指令表示为枚举,但同时也想访问指令的操作码而无需其数据。在此示例中,操作码是指令的enum标签。

示例

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,
            }
        }
    }
};

依赖项

~260–700KB
~17K SLoC