#枚举 #参考 #包装器 #引用 #过程宏

无需std enum-ref

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

2个不稳定版本

0.1.0 2023年3月27日
0.0.0 2023年3月27日

#11#ref

每月 22 次下载

MIT 许可证

9KB

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

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

#[derive(EnumRef)]#[derive(EnumMut)]

这个crate提供#[derive(EnumRef)]#[derive(EnumMut)]过程宏,这些宏为Rust的enum类型生成引用包装器。从EnumRefEnumMut派生也将实现相应的trait,这允许访问和实例化生成的引用包装器。

动机

生成的引用类型与Rust中enum实例的默认引用略有不同,即只有enum数据是引用,而enum判别符仍然内联。当需要拥有enum引用包装器时,如果用户具有具有大量变体的enum类型,这将特别有用,因为这些变体使得维护原始enum类型和引用包装器之间的对应关系变得费力。

如果用户主要对查询enum判别符感兴趣,这甚至可能带来性能提升。然而,性能不是这个crate的主要用途。

我开发这个库的个人动机是允许更高效的枚举(enum)编码。通常情况下,枚举实例使用对齐的区分符编码,所有变体共享与最大枚举变体相同的size_of。这有一个缺点,即默认的Rust enum编码可能会浪费很多空间。当我们尝试以空间高效的方式编码Rust enum实例时,我们仍然想访问编码后的枚举实例,但我们不能使用常规引用,因为这些引用假设对齐的枚举编码,这不会是实际情况。这就是我们的新引用包装类型发挥作用的地方,因为我们可以使用它们来处理我们的新编码。

使用方法

以下演示了如何使用此库提供的宏过程。

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

// Access and name the generated `enum` reference wrapper types as follows:
type TestRef<'a> = <Test as EnumRef>::Ref<'a>;
type TestMut<'a> = <Test as EnumMut>::Mut<'a>;

// Creates reference wrappers of `enum` instances as follows:
let test = Test::C(42);
let test_ref: TestRef = <Test as EnumRef>::as_ref(&test);
match (&test, test_ref) {
    (Test::C(a0), TestRef::C(a1)) => assert_eq!(a0, a1),
    _ => panic!("something wen't wrong ..."),
}

生成的代码

例如,上面的#[derive(EnumRef)]将生成大致如下Rust代码

const _: () = {
    #[derive(::core::fmt::Debug)]
    #[repr(u8)]
    pub enum TestRef<'__enum_ref_lt> {
        A,
        B = 42,
        C(&'__enum_ref_lt i32),
        D(&'__enum_ref_lt i32, &'__enum_ref_lt i64),
        E {
            a: &'__enum_ref_lt i32,
        },
        F {
            a: &'__enum_ref_lt i32,
            b: &'__enum_ref_lt i64,
        },
    }

    impl ::enum_ref::EnumRef for Test {
        type Ref<'__enum_ref_lt> where Self: '__enum_ref_lt =
                TestRef<'__enum_ref_lt> where Self: '__enum_ref_lt;
        fn as_ref(&self) -> <Self as ::enum_ref::EnumRef>::Ref<'_> {
            type __enum_ref_EnumRef_Ref<'__enum_ref_lt> =
                <Test as ::enum_ref::EnumRef>::Ref<'__enum_ref_lt>;
            match self {
                Self::A => __enum_ref_EnumRef_Ref::A,
                Self::B => __enum_ref_EnumRef_Ref::B,
                Self::C(_0) => __enum_ref_EnumRef_Ref::C(_0),
                Self::D(_0, _1) => __enum_ref_EnumRef_Ref::D(_0, _1),
                Self::E { a } => __enum_ref_EnumRef_Ref::E { a },
                Self::F { a, b } => __enum_ref_EnumRef_Ref::F { a, b },
            }
        }
    }
};

依赖

~290–750KB
~18K SLoC