1 个不稳定版本
0.1.0 | 2022年9月11日 |
---|
#10 在 #misaligned
11KB
96 代码行数(不包括注释)
packed_bools:一个轻量级的布尔值打包的位操作库
想在一个结构体中嵌入多个 bool
值吗?使用 core
/std
,你需要为每个值支付 1 字节的空间,以便每个单独的 bool
都可以寻址。对于内存/存储敏感的应用程序,我们真的需要一个更高效的替代方案。这就是 packed_bools
的出现。
crates.io 上已经有一些位操作库。快速搜索会发现大约有五六款流行的库。那么这个库有什么不同呢?它是开发友好且易用的。当我提到我的猫时,我不会用他的空间坐标来称呼他,而是用他的名字“Ron”(或者如果他只是把我的耳机扔到地上,就叫他“Ronald”)。同样,我也不想称某个大型类型中的单个位为“这个类型的第2位”或“那个类型的第5位”... 还得在某个地方记录下来,以免忘记哪个位是哪个... 然后还要实现位操作来对这些位执行操作。我想通过我选择的标志名来引用布尔值——我想给我的位命名。
这个库提供了一个派生宏 PackedBooleans
,你可以用它来注释一个(或多个)core::primitive::u8
,其中你可以提供最多 8 个布尔标志名(每个 u8
)。
这个库没有引入新的类型。它只是在你提供的结构体上实现了通过名称操作和检索位的方法。
示例用法
use packed_bools::PackedBooleans;
#[derive(Default, PackedBooleans)]
pub struct FooStruct<'a, T=()> {
#[pack_bools(active, admin, discount, premium, og, frozen, kyc, tos_agree)]
pub booleans: u8,
pub an_option_with_generics: Option<&'a T>,
}
// Initialize your struct
let mut foo_struct = FooStruct::<()>::default();
// Set the values of each bit individually
foo_struct.set_active(true);
foo_struct.set_admin(false);
foo_struct.set_discount(true);
foo_struct.set_premium(false);
foo_struct.set_og(false);
foo_struct.set_frozen(true);
foo_struct.set_kyc(false);
foo_struct.set_tos_agree(true);
// Read the values of each bit individually
assert_eq!(foo_struct.get_active(), true);
assert_eq!(foo_struct.get_admin(), false);
assert_eq!(foo_struct.get_discount(), true);
assert_eq!(foo_struct.get_premium(), false);
assert_eq!(foo_struct.get_og(), false);
assert_eq!(foo_struct.get_frozen(), true);
assert_eq!(foo_struct.get_kyc(), false);
assert_eq!(foo_struct.get_tos_agree(), true);
// Do not do this!
// foo_struct.booleans += 5;
是的,我知道...一个更复杂的库会使用一个 #[repr(transparent)]
包装器围绕 u8
来确保用户不操作 u8。或者,如果用户需要 >8 个标志,也许可以扩展到 u16
或 u32
。如果您想在库中实现这个功能,请随时提交一个 PR ;)。
依赖关系
~1.5MB
~35K SLoC