#enums #reference #ref #wrapper #proc-macro

无std enum-ref-macro

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

2个不稳定版本

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

#39#ref

每月 28 次下载
enum-ref 中使用

MIT 许可证

21KB
207

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

此包提供了 #[derive(EnumRef)]#[derive(EnumMut)] 过程宏,它们为Rust enum 类型生成引用包装器。使用 EnumRefEnumMut 派生还将实现相应的特性,允许访问和实例化生成的引用包装器。

动机

生成的引用类型与Rust默认的引用到枚举实例的引用略有不同,因为只有枚举数据是引用,而枚举的区分符仍然是内联的。当需要枚举引用包装器时,这个crate对于用户拥有大量变体的枚举类型特别有用,因为这会使维护原始枚举类型和引用包装器之间的镜像变得劳动密集。

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

我个人对创建这个crate的动机是允许更空间高效的枚举编码。通常,枚举实例使用对齐的区分符进行编码,并且所有变体都与最大的枚举变体具有相同的size_of。这的缺点是默认的Rust枚举编码可能会浪费很多空间。当尝试以空间效率对Rust枚举实例进行编码时,我们仍然想要访问编码后的枚举实例,但我们不能使用对它们正常的引用,因为这些引用假设对齐的枚举编码,而这将不会是情况。这就是我们的新引用包装器类型发挥作用的地方,因为我们可以用它们来执行新的编码。

用法

以下是如何使用此crate提供的proc.宏的示例。

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

依赖关系

~285–740KB
~18K SLoC