#boolean #bits #bit-manipulation #bit #misaligned #unaligned

无std packed_bools

一个轻量级的布尔值打包的位操作库

1 个不稳定版本

0.1.0 2022年9月11日

#10#misaligned

MIT/Apache

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 个标志,也许可以扩展到 u16u32。如果您想在库中实现这个功能,请随时提交一个 PR ;)。

依赖关系

~1.5MB
~35K SLoC