2个不稳定版本
0.1.0 | 2023年3月27日 |
---|---|
0.0.0 | 2023年3月27日 |
#11 在 #ref
每月 22 次下载
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 |
---|---|---|
[][2] | [][4] | [][6] |
#[derive(EnumRef)]
和 #[derive(EnumMut)]
这个crate提供#[derive(EnumRef)]
和#[derive(EnumMut)]
过程宏,这些宏为Rust的enum
类型生成引用包装器。从EnumRef
或EnumMut
派生也将实现相应的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