#bitmap #bit-flags #unsigned-integer #bit #flags #bits #static

bin+lib fixed_bitmaps

A small crate implementing bitmap functionality around primitive Rust unsigned integers

19 releases (9 breaking)

0.10.2 Nov 7, 2021
0.9.3 Oct 14, 2021

#1101 in Data structures

33 downloads per month

MIT/Apache

145KB
3.5K SLoC

Fixed Bitmaps

Build Status API crates.io Downloads License

Implement bitmap functionality around primitive Rust unsigned integers. I ended up making this after wanting a simple data structure to use for bit flags. Other options definitely exist, but some looked intimidating and others I didn't find till after I made this, and besides, I just wanted to make a crate I was willing to publish!

These bitmaps are simply for when you want a data structure to hold boolean flags, which can be AND-ed, OR-ed and XOR-ed together, in as compressed a format as possible, while still holding enough functionality to easily view the bitmap for display, or get a particular bit. Working with this crate is a breeze, and if you want a relatively small dependency that's stable, lightning fast, and easy to use, this could be the one for you!

One thing this crate is not is flexible! The largest bitmaps you can make with this are 128 bits long, so if you want something larger, you may wish to visit other crates that implement this. The one that I would recommend, which this crate turned out to become very similar to, is bit-vec.

Features

  • There are now wrappings for all basic types of unsigned integers, from u8 up to u128, along with a wrapper for usize (BitmapArch).
  • Both bitwise (and, or, xor, not) and arithmetic (add, subtract, multiply, divide) operations supported between bitmaps, and between bitmaps and their respective integer type.
  • Implements Display to show the bitmap in all its 1's and 0's glory. (May end up changing this to the Debug trait however, that'll have to be something to think about before releasing 1.0.0).
  • Easy conversion between a Bitmap and the integer type it's associated with using a dedicated method or the dereference operator *.
  • Left and right shifts now implemented

Code examples

use fixed_bitmaps::Bitmap64;

// Multiple ways to create a new bitmap
let empty = Bitmap64::default();
let empty = Bitmap64::new(false);

let full = Bitmap64::from(u64::MAX);
let full = Bitmap64::new(true);

let mask = Bitmap64::create_bit_mask(2, 6, true); // Creates bitmap with last bits 111100
let mask = Bitmap64::create_bit_mask(2, 6, false); // Creates bitmap 11..11000011

// Equivalent ways to create a bitmap with last bits 1001
let bitmap = Bitmap64::from(9);
let bitmap = Bitmap64::from(0b1001);

// Sets the 7th least significant bit when creating a new
// bitmap (indexing starts at 0)
let mut bitmap = Bitmap64::from_set(6).unwrap();

// Use the set() method to work with specific bits
bitmap.set(6, false).unwrap();
bitmap.set(42, true).unwrap();

// Use get() to know the value of a specific bit
println!("Bit at index 42: {}", bitmap.get(42).unwrap());

// Freely use boolean operators &, |, and ^
let bitmap1 = Bitmap64::from(0b1001);
let bitmap2 = Bitmap64::from(0b1010);

let and = bitmap1 & bitmap2;
let or = bitmap1 | bitmap2;
let xor = bitmap1 ^ bitmap2;

// The following also works exactly the same
let and = bitmap1 & 0b1010;
let or = bitmap1 | 0b1010;
let xor = bitmap1 ^ 0b1010;

// You can also use the not operator ! to get the flipped version of
// the bitmap
let flipped = !bitmap;

// Aritmetic operators are currently used as exactly that, the following
// is guarunteed to continue working as it does
let add = bitmap1 + 10;
let sub = bitmap1 - 4;
let mul = bitmap2 * 2;
let div = bitmap2 / 2;

// The following works exactly as above, but is likely to change in
// favour of set operations in the major update to 1.0.0
let add = bitmap1 + Bitmap64::from(10);
let sub = bitmap1 - Bitmap64::from(4);
let mul = bitmap2 * Bitmap64::from(2);
let div = bitmap2 / Bitmap64::from(2);

// Left and right shifts work exactly as they do with integers
let lsh = bitmap1 << 3;
let rsh = bitmap2 >> 1;

To be done

  • Documentation is always something to be improved, any documentation changes or minor bug fixes result in a patch update.
  • Anytime a new structure is defined and implemented, or a new function defined, a minor update will be published.
  • When this has been fully tested and benchmarked, and any other important components I might have missed have been added, I will publish fixed_bitmaps 1.0.0 as a major update, to indicate its readyness for full production.
  • The final struct to create will likely be the BitmapLarge struct, or something similar. This will have a set size, but the user can define what that size is. The aim is to have a struct that cannot grow or shrink, but can be given a large capacity from the beginning. This is similar to bit-vec, just without the dynamic growing property, so I think it should be easier to store on the stack rather than the heap, resulting in better performance.

Contributions

Contributions are always welcome, whether for better documentation, bugfixing or optimizations in the code itself!

When making changes, only do so in the following files (unless of course you plan to add a new module or something of the sort):

  • fixed_bitmaps/src/primitives/bitmap128.rs
  • fixed_bitmaps/tests/primitives/bitmap128.rs
  • fixed_bitmaps/src/oversized/bitmap_kb.rs
  • fixed_bitmaps/tests/oversized/bitmap_kb.rs

You can then run cargo run on this project, and it will propogate changes to those files through to all of the other files in their respective directories, adapting the changes to match the particular primitive each module aims to support.

Run cargo test to make sure your changes pass the tests currently implemented, or to run new tests that you set up!

Dependencies

~0.4–1MB
~22K SLoC