# bittle [github](https://github.com/udoprog/bittle) [crates.io](https://crates.io/crates/bittle) [docs.rs](https://docs.rs/bittle) [build status](https://github.com/udoprog/bittle/actions?query=branch%3Amain) Zero-cost bitsets over native Rust types. The name `bittle` comes from `bit` and `little`. Small bitsets!
## Usage Add `bittle` as a dependency in your `Cargo.toml`:
```toml [dependencies] bittle = "0.6.0" ```
## Guide 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 = 0b00000000_00000000_00000000_00010001u32; assert!(n.iter_ones().eq([0, 4])); let array_of_arrays: [[u8; 4]; 2] = [[16, 0, 0, 0], [0, 0, 1, 0]]; assert!(array_of_arrays.iter_ones().eq([4, 48])); let mut vec: Vec = vec![0, 1, 2, 3]; assert!(vec.iter_ones().eq([32, 65, 96, 97])); ```
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 array_of_arrays: [[u8; 4]; 2] = bittle::set![4, 48]; assert!(array_of_arrays.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 = vec![0u32; 4]; vec.set_bit(32); vec.set_bit(65); vec.set_bit(96); vec.set_bit(97); assert!(vec.iter_ones().eq([32, 65, 96, 97])); assert_eq!(vec, [0, 1, 2, 3]); ```
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: * Something like `is_empty` becomes `all_zeros` - since with bits you're thinking about "ones and zeros". * Testing if a bit is set is `test_bit`, or in general adding the `*_bit` suffix to operations over individual bits. * Clearing all bits becomes `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.set_bit(15); assert!(set.test_bit(15)); set.union_assign(&bittle::set![31, 7]); assert!(set.test_bit(31) && set.test_bit(7)); set.clear_bit(31); assert!(!set.test_bit(31)); set.clear_bits(); assert!(set.all_zeros()); ```
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.set_bit(0); assert!(m.join_ones(&elements).eq([&10])); m.set_bit(2); assert!(m.join_ones(&elements).eq([&10, &101])); ```
[`BigEndian`]: https://docs.rs/bittle/latest/bittle/struct.BigEndian.html [`Bits::join_ones`]: https://docs.rs/bittle/latest/bittle/trait.Bits.html#method.join_ones [`Bits::test_bit_in`]: https://docs.rs/bittle/latest/bittle/trait.Bits.html#method.test_bit_in [`Bits::test_bit_le`]: https://docs.rs/bittle/latest/bittle/trait.Bits.html#method.test_bit_le [`Bits`]: https://docs.rs/bittle/latest/bittle/trait.Bits.html [`BitsMut`]: https://docs.rs/bittle/latest/bittle/trait.BitsMut.html [`BitsOwned`]: https://docs.rs/bittle/latest/bittle/trait.BitsOwned.html [`Copy`]: https://doc.rust-lang.org/std/marker/trait.Copy.html [`set!`]: https://docs.rs/bittle/latest/bittle/macro.set.html [`u32`]: https://doc.rust-lang.org/std/primitive.u32.html [`u8`]: https://doc.rust-lang.org/std/primitive.u8.html [see issue #2]: https://github.com/udoprog/bittle/pull/2