#bitmap #bit-array #bitset

无std cbitmap

传统、紧凑和核心(无std)位图

6个版本

0.3.2 2023年3月27日
0.3.1 2023年3月27日
0.2.0 2023年3月26日
0.1.1 2023年3月26日

101无标准库

Download history 21/week @ 2024-04-02 1/week @ 2024-04-16

73 每月下载量

MIT 协议

60KB
693

Build Status MIT License Crate Doc

cbitmap

传统、紧凑和核心(无std)位图。

使用场景

当您想要维护一个包含大量但固定数量的位的位图时,建议您使用此crate。特别是,当您关心内存使用/对齐时,因为cbitmap几乎不浪费空间。

例如,您可能想要管理一组资源,这些资源可以用两种状态来描述,位图非常适合您。

如果您想维护一组小的标志,如2或3,我们建议使用flagset

位图最全面和成熟的实现可能是bitvec。如果您关心成熟度,建议您使用它。

此外,bitset-core是另一个强大的crate,它实现了紧凑的位图特质。然而,bitset-corecbitmap之间的实现相当不同。

此外,cbitmap的性能尚未经过测试,因为它处于alpha版本。如果您最关心性能,请在选择之前仔细考虑。

功能

我们提供了一个crate::bitmap::Bitmap类型

pub struct Bitmap<const BYTES: usize> {
    bits: [u8; BYTES],
}

建议您使用宏来创建新的位图

use cbitmap::bitmap::*;

let map = newmap!(0b_01; 2);

请参阅crate::he_lang

位图可以通过传统的方式操作,如Bitmap::test()Bitmap::set()Bitmap::reset()Bitmap::flip()Bitmap::at()。请参阅文档以获取详细示例。

位图实际上是 u8 数组的包装 [u8; BYTES]。它可以放在内存的多个地方。例如,如果映射相对较小,如8或16位,您可以在栈上安全地放置它。如果它更大,如256或1024位,您可能希望将其放在堆上。

示例

下面是一个简单的例子

use cbitmap::bitmap::*;
 
// A macro are provided to create a bitmap.
let mut map = newmap!(;16);

// There is a set of methods to manipulate the bitmap:
map.set(10);
map.reset(10);
map.flip(10);

// Some C++ like methods are provided:
assert_eq!(map.test(10), true);
assert_eq!(map.any(), true);
assert_eq!(map.none(), false);

// Also provide other useful methods:
assert_eq!(map.find_first_one(), 10);

// You can access a single bit using wrappers:
let mut bit = map.at_mut(10);
assert_eq!(*bit, true);
bit.flip();
assert_eq!(*map.at(10), false);

请参阅 Bitmap 的文档和示例目录,以获取详细示例。

您可以使用 cargo run --example <name> 来运行我们提供的示例。一个简单的示例是 bitmap-base,另一个关于实际应用的详细示例是 bitmap-usecase,其中位图用于管理原始内存资源。

当前约束

泛型常量表达式

位图通过 BYTES 指定其字节数。这与C++中的传统 bitset<N> 略有不同,其中 N 表示位大小。我们以这种方式实现位图,以保持在rust-stable上,因为 #![feature(generic_const_exprs)] 尚未支持,因此不允许这样做

// requiring #![feature(generic_const_exprs)]
pub struct Bitmap<const N: usize> {
    bits: [u8; (N + 7) / 8],
}

我们提供了一种替代方法,让您指定位大小。宏 crate::newmap 实现了这一点

const BITS: usize = 16;
let map = newmap!(;BITS);
let another = newmap!(;BITS * 2);

原则上,在实例化结构体时使用 constexpr 是可能的

// allowed:
let map = Bitmap::<{64 / 8}>::new();

索引

C++ 中的 bitset<N> 可以通过索引运算符 [] 进行索引。我们在实现此功能时遇到了一些问题。具体来说,为结构体实现 core::ops::IndexMut 如此

impl IndexMut for T {
    type Output = U;
    fn index(&mut self, index: usize) -> &mut Self::Output { ... }
}

&mut Self::Output 中的引用要求 self 拥有索引输出。

Bitmap 中,Output 必须是 "bits"。有必要使用包装类型来提供访问单个位的接口。我们提供了 BitRefBitRefMut 作为包装器。

然而,位图不应该包含大量的包装器,以便节省内存。

由于这个问题,我们只提供了 Bitmap::at_mut() 作为方法来多重索引位图。

值得注意的是,我们提供了 Bitmap::at() 来获取 BitRef,我们还提供了不可变的 Index。然而,由于类似的问题,不可变的 Index 只返回一个 bool 值,而不是 BitRef

更新内容

  • 0.3.2

    • 添加 Index
    • 添加 as_ref()as_mut()as_ptr()as_mut_ptr()
    • 将通用方法如 set() 封装到特质中。
  • 0.3.1

    • 添加基本基准测试。
    • 添加与 C++ 兼容的新方法:Bitmap::any()Bitmap::none()Bitmap::all()Bitmap::count()Bitmap::test()
    • 添加有用方法:[Bitmap::find_first_one()]、[Bitmap::find_first_zero()]。
    • 添加示例 bitmap-usecase,展示使用 bitmap 管理原始内存资源的情况。
  • 0.3.0

    • 通过删除 Option 优化内存使用(bitmap 的大小比泛型大 1 字节,这不利于内存对齐)。
    • 添加新方法:FillPrefix。
    • 改进宏的创建:现在长度参数接收 const 表达式。
  • 0.2.0

    • 添加构建宏。
  • 0.1.1

    • 更新文档。
  • 0.1.0

    • 首次发布。

无运行时依赖