Zero-cost bitsets over native Rust types.
The name bittle
comes from bit
and little
. Small bitsets!
Add bittle
as a dependency in your Cargo.toml
:
toml
[dependencies]
bittle = "0.5.1"
A bit is always identified by a [u32
] by its index, and the exact location
for a bit in a primitive numbers is defined by its endianness, which is
[BigEndian
] by default.
[BigEndian
] indexing grows from right to left, such as the following
[u8
] literal:
text
0b0010_0010u8
^ ^- index 1
'------ index 5
To interact with these bits we define the [Bits
], [BitsMut
], and
[BitsOwned
] traits. These traits are implemented for primitive types such
as u32
, [u32; 4]
, or &[u32]
:
```rust use bittle::Bits;
let array: [u32; 4] = [0, 1, 2, 3]; assert!(array.iter_ones().eq([32, 65, 96, 97]));
let n = 0b00000000000000000000000000010001u32; assert!(n.iterones().eq([0, 4]));
let arrayofarrays: [[u8; 4]; 2] = [[16, 0, 0, 0], [0, 0, 1, 0]]; assert!(arrayofarrays.iter_ones().eq([4, 48]));
let mut vec: Vec
We also provide the [set!
] macro, which is a zero-cost convenience method
for constructing primitive forms of bit sets:
```rust use bittle::Bits;
let array: [u32; 4] = bittle::set![32, 65, 96, 97]; assert!(array.iter_ones().eq([32, 65, 96, 97]));
let n: u32 = bittle::set![0, 4]; assert!(n.iter_ones().eq([0, 4]));
let arrayofarrays: [[u8; 4]; 2] = bittle::set![4, 48]; assert!(arrayofarrays.iter_ones().eq([4, 48])); ```
Since a vector is not a primitive bit set, it could instead make use of
[BitsMut
] directly:
```rust use bittle::{Bits, BitsMut};
let mut vec: Vec
Due to how broadly these traits are implemented, we also try to avoid using names which are commonly used in other APIs, instead opt for bit-specific terminology such as:
is_empty
becomes all_zeros
- since with bits you're
thinking about "ones and zeros".test_bit
, or in general adding the *_bit
suffix to operations over individual bits.clear_bits
, or in general adding the *_bits
suffix when operating over all bits.```rust use bittle::{Bits, BitsMut};
let mut set = [0u16; 2];
set.setbit(15); assert!(set.testbit(15));
set.unionassign(&bittle::set![31, 7]); assert!(set.testbit(31) && set.test_bit(7));
set.clearbit(31); assert!(!set.testbit(31));
set.clearbits(); assert!(set.allzeros()); ```
Some other interesting operations, such as [Bits::join_ones
] are available,
allowing bitsets to act like masks over other iterators:
```rust use bittle::{Bits, BitsMut};
let elements = vec![10, 48, 101]; let mut m = 0u128;
m.setbit(0); assert!(m.joinones(&elements).eq([&10])); m.setbit(2); assert!(m.joinones(&elements).eq([&10, &101])); ```