growable_bitmap/lib.rs
1//! A crate providing a growable compact boolean array that can be
2//! parameterized on its storage.
3//!
4//! See the `GrowableBitMap` type for more information.
5//!
6//! # TODO:
7//!
8//! This crate is not feature-complete at all. Below are some features I want
9//! to add before marking it as `1.0`:
10//!
11//! - `BitOr` (with another `GrowableBitMap`).
12//! - `BitOrAssign` (with another `GrowableBitMap`).
13//! - `BitAnd` (with another `GrowableBitMap`).
14//! - `BitAndAssign` (with another `GrowableBitMap`).
15//! - `BitXor` (with another `GrowableBitMap`).
16//! - `BitXorAssign` (with another `GrowableBitMap`).
17//!
18//! - When `const-generics` become available, possibly use them as storage ?
19//!
20//! - [Rust 1.48.0+ / Intra-doc links]: Use intra-doc links in documentation.
21//! Right now there are no links because they're painful to write once you've
22//! been introduced to the wonder intra-doc links are.
23use std::fmt;
24
25mod storage;
26pub use storage::BitStorage;
27
28/// A growable compact boolean array that can be parameterized on its storage.
29///
30/// Bits are stored contiguously. The first value is packed into the least
31/// significant bits of the first word of the backing storage.
32///
33/// The storage must implement the unsafe trait `BitStorage`.
34///
35/// # Caveats
36///
37/// - The `GrowableBitMap::set_bit` method may allocate way too much memory
38/// compared to what you really need (if for example, you only plan to set
39/// the bits between 1200 and 1400). In this case, storing the offset of
40/// 1200 somewhere else and storing the values in the range `0..=200` in the
41/// `GrowableBitMap` is probably the most efficient solution.
42#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
43pub struct GrowableBitMap<S>
44where
45 S: BitStorage,
46{
47 // The storage for the bits.
48 bits: Vec<S>,
49}
50
51impl<S> fmt::Debug for GrowableBitMap<S>
52where
53 S: BitStorage + fmt::Debug,
54{
55 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
56 fmt.debug_list().entries(self.bits.iter()).finish()
57 }
58}
59
60impl<S> GrowableBitMap<S>
61where
62 S: BitStorage,
63{
64 /// Creates a new, empty `GrowableBitMap`.
65 ///
66 /// This does not allocate anything.
67 ///
68 /// # Examples
69 ///
70 /// ```rust
71 /// use growable_bitmap::{GrowableBitMap, BitStorage};
72 ///
73 /// assert!(GrowableBitMap::<u8>::new().is_empty());
74 /// ```
75 pub fn new() -> Self {
76 Self { bits: Vec::new() }
77 }
78
79 /// Constructs a new, empty `GrowableBitMap` with the specified capacity
80 /// **in bits**.
81 ///
82 /// When `capacity` is zero, nothing is allocated.
83 ///
84 /// When `capacity` is not zero, the bit `capacity - 1` can be set without
85 /// any other allocation and the returned `GrowableBitMap` is guaranteed
86 /// to be able to hold `capacity` bits without reallocating (and maybe more
87 /// if the given `capacity` is not a multiple of the number of bits in one
88 /// instance of the backing storage).
89 ///
90 /// # Examples
91 ///
92 /// ```rust
93 /// use growable_bitmap::{GrowableBitMap, BitStorage};
94 ///
95 /// let mut b = GrowableBitMap::<u16>::with_capacity(16);
96 /// assert!(b.is_empty());
97 /// assert_eq!(b.capacity(), 16);
98 ///
99 /// b.set_bit(15);
100 /// assert_eq!(b.capacity(), 16);
101 ///
102 /// b.set_bit(17);
103 /// assert!(b.capacity() >= 16);
104 /// ```
105 pub fn with_capacity(capacity: usize) -> Self {
106 if capacity == 0 {
107 return Self::new();
108 }
109
110 let div = capacity / S::BITS_IN_STORAGE;
111 // Ensures the allocated capacity is enough for values like 125 with a
112 // storage of `u8`:
113 //
114 // - `div` is 15
115 // - `capacity % S::BITS_IN_STORAGE` is 5 so `rem` is 1.
116 //
117 // The final capacity will be 16 `u8`s -> 128 bits, enough for the
118 // 125 bits asked for.
119 let rem = (capacity % S::BITS_IN_STORAGE != 0) as usize;
120
121 Self {
122 bits: Vec::with_capacity(div + rem),
123 }
124 }
125
126 /// `true` if the `GrowableBitMap` is empty.
127 ///
128 /// # Examples
129 ///
130 /// ```rust
131 /// use growable_bitmap::{GrowableBitMap, BitStorage};
132 ///
133 /// let mut b = GrowableBitMap::<u32>::new();
134 /// assert!(b.is_empty());
135 ///
136 /// b.set_bit(25);
137 /// assert!(!b.is_empty());
138 /// ```
139 pub fn is_empty(&self) -> bool {
140 self.bits.is_empty() || self.bits.iter().all(|bits| bits.is_empty())
141 }
142
143 /// Gets the bit at the given index and returns `true` when it is set to 1,
144 /// `false` when it is not.
145 ///
146 /// This will **not** panic if the index is out of range of the backing
147 /// storage, only return `false`.
148 ///
149 /// # Examples
150 ///
151 /// ```rust
152 /// use growable_bitmap::{GrowableBitMap, BitStorage};
153 ///
154 /// let mut b = GrowableBitMap::<u64>::new();
155 /// assert!(!b.get_bit(0));
156 /// assert!(!b.get_bit(15));
157 ///
158 /// b.set_bit(15);
159 /// assert!(!b.get_bit(0));
160 /// assert!(b.get_bit(15));
161 /// ```
162 pub fn get_bit(&self, index: usize) -> bool {
163 let bits_index = index / S::BITS_IN_STORAGE;
164
165 // Since the bits_index does not exist in the storage, the bit at
166 // `index` is logically 0.
167 if self.bits.len() <= bits_index {
168 return false;
169 }
170
171 let elem = &self.bits[bits_index];
172
173 // SAFETY: we have ensure throught the steps above that the index
174 // passed to `elem.set_bit` is in range of `0..S::BITS_IN_STORAGE`.
175 //
176 // Example with a `u8`:
177 //
178 // `u8::BITS_IN_STORAGE` is 8.
179 // `index` is 21.
180 //
181 // `bits_index` = 2
182 // `index - bits_index * S::BITS_IN_STORAGE` = 21 - 2 * 8 = 5 < 8
183 unsafe { elem.get_bit(index - bits_index * S::BITS_IN_STORAGE) }
184 }
185
186 /// Sets the bit at the given index and returns whether the bit was set
187 /// to 1 by this call or not.
188 ///
189 /// Note: This will grow the backing storage as needed to have enough
190 /// storage for the given index. If you set the bit 12800 with a storage of
191 /// `u8`s the backing storage will allocate 1600 `u8`s since
192 /// `sizeof::<u8>() == 1` byte.
193 ///
194 /// See also the `Caveats` section on `GrowableBitMap`.
195 ///
196 /// # Examples
197 ///
198 /// ```rust
199 /// use growable_bitmap::{GrowableBitMap, BitStorage};
200 ///
201 /// let mut b = GrowableBitMap::<u128>::new();
202 /// assert!(b.set_bit(0)); // Bit 0 was not set before, returns true.
203 /// assert!(!b.set_bit(0)); // Bit 0 was already set, returns false.
204 ///
205 /// assert!(b.set_bit(255)); // The bitmap will grow as needed to set the bit.
206 /// ```
207 pub fn set_bit(&mut self, index: usize) -> bool {
208 let bits_index = index / S::BITS_IN_STORAGE;
209
210 // Ensure there are enough elements in the `bits` storage.
211 if self.bits.len() <= bits_index {
212 self.bits.resize_with(bits_index + 1, S::empty);
213 }
214
215 let elem = &mut self.bits[bits_index];
216
217 // SAFETY: we have ensure throught the steps above that the index
218 // passed to `elem.set_bit` is in range of `0..S::BITS_IN_STORAGE`.
219 //
220 // Example with a `u8`:
221 //
222 // `u8::BITS_IN_STORAGE` is 8.
223 // `index` is 21.
224 //
225 // `bits_index` = 2
226 // `index - bits_index * S::BITS_IN_STORAGE` = 21 - 2 * 8 = 5 < 8
227 unsafe { elem.set_bit(index - bits_index * S::BITS_IN_STORAGE) }
228 }
229
230 /// Clears the bit at the given index and returns whether the bit was set
231 /// to 0 by this call or not.
232 ///
233 /// Note: this function will never allocate nor free memory, even when
234 /// the bit being cleared is the last 1 in the value at the end of the
235 /// backing storage.
236 ///
237 /// # Examples
238 ///
239 /// ```rust
240 /// use growable_bitmap::{GrowableBitMap, BitStorage};
241 ///
242 /// let mut b = GrowableBitMap::<u8>::new();
243 /// assert!(!b.clear_bit(3)); // Bit 0 was not set before, returns false.
244 ///
245 /// b.set_bit(3);
246 /// assert!(b.clear_bit(3));
247 /// ```
248 ///
249 /// Testing the effects on capacity:
250 ///
251 /// ```rust
252 /// use growable_bitmap::{GrowableBitMap, BitStorage};
253 ///
254 /// let mut b = GrowableBitMap::<u8>::new();
255 /// b.set_bit(125);
256 ///
257 /// let old_capa = b.capacity();
258 /// b.clear_bit(125);
259 /// assert_eq!(old_capa, b.capacity());
260 /// ```
261 pub fn clear_bit(&mut self, index: usize) -> bool {
262 let bits_index = index / S::BITS_IN_STORAGE;
263
264 // Since the bits_index does not exist in the storage, the bit at
265 // `index` is logically 0.
266 if self.bits.len() <= bits_index {
267 return false;
268 }
269
270 let elem = &mut self.bits[bits_index];
271
272 // SAFETY: we have ensure throught the steps above that the index
273 // passed to `elem.set_bit` is in range of `0..S::BITS_IN_STORAGE`.
274 //
275 // Example with a `u8`:
276 //
277 // `u8::BITS_IN_STORAGE` is 8.
278 // `index` is 21.
279 //
280 // `bits_index` = 2
281 // `index - bits_index * S::BITS_IN_STORAGE` = 21 - 2 * 8 = 5 < 8
282 unsafe { elem.clear_bit(index - bits_index * S::BITS_IN_STORAGE) }
283 }
284
285 /// Clears the bitmap, removing all values (setting them all to 0).
286 ///
287 /// This method has no effect on the allocated capacity of the bitmap.
288 ///
289 /// # Examples
290 ///
291 /// ```rust
292 /// use growable_bitmap::{GrowableBitMap, BitStorage};
293 ///
294 /// let mut b = GrowableBitMap::<u16>::new();
295 /// b.set_bit(4);
296 /// assert!(!b.is_empty());
297 ///
298 /// b.clear();
299 /// assert!(b.is_empty());
300 /// ```
301 ///
302 /// Testing the effects on capacity:
303 ///
304 /// ```rust
305 /// use growable_bitmap::{GrowableBitMap, BitStorage};
306 ///
307 /// let mut b = GrowableBitMap::<u16>::new();
308 /// b.set_bit(125);
309 ///
310 /// let old_capa = b.capacity();
311 /// b.clear();
312 /// assert_eq!(old_capa, b.capacity());
313 /// ```
314 pub fn clear(&mut self) {
315 self.bits.clear();
316 }
317
318 /// Counts the number of bits that are set to 1 in the whole bitmap.
319 ///
320 /// # Examples
321 ///
322 /// ```rust
323 /// use growable_bitmap::{GrowableBitMap, BitStorage};
324 ///
325 /// let mut b = GrowableBitMap::<u32>::new();
326 /// assert_eq!(b.count_ones(), 0);
327 ///
328 /// b.set_bit(2);
329 /// assert_eq!(b.count_ones(), 1);
330 ///
331 /// b.set_bit(9);
332 /// assert_eq!(b.count_ones(), 2);
333 ///
334 /// b.clear();
335 /// assert_eq!(b.count_ones(), 0);
336 /// ```
337 pub fn count_ones(&self) -> usize {
338 self.bits
339 .iter()
340 .map(|store| store.count_ones() as usize)
341 .sum::<usize>()
342 }
343
344 /// Returns the number of bits the bitmap can hold without reallocating.
345 ///
346 /// # Examples
347 ///
348 /// ```rust
349 /// use growable_bitmap::{GrowableBitMap, BitStorage};
350 ///
351 /// let mut b = GrowableBitMap::<u64>::new();
352 /// assert_eq!(b.capacity(), 0);
353 ///
354 /// b.set_bit(380);
355 /// assert_eq!(b.capacity(), 384);
356 /// ```
357 pub fn capacity(&self) -> usize {
358 self.bits.capacity() * S::BITS_IN_STORAGE
359 }
360
361 /// Shrinks the capacity of the `GrowableBitMap` as much as possible.
362 ///
363 /// It will drop down as close as possible to the length needed to store
364 /// the last bit set to 1 and not more but the allocator may still inform
365 /// the bitmap that there is space for a few more elements.
366 ///
367 /// # Examples
368 ///
369 /// ```rust
370 /// use growable_bitmap::{GrowableBitMap, BitStorage};
371 ///
372 /// let mut b = GrowableBitMap::<u128>::with_capacity(381);
373 ///
374 /// b.set_bit(127);
375 /// b.set_bit(380);
376 /// assert_eq!(b.capacity(), 384);
377 ///
378 /// b.clear_bit(380);
379 /// b.shrink_to_fit();
380 /// assert_eq!(b.capacity(), 128);
381 /// ```
382 pub fn shrink_to_fit(&mut self) {
383 // Ignoring the values at the end that are 0.
384 let last_set_bit_index = self
385 .bits
386 .iter()
387 .rev()
388 .skip_while(|&store| store.is_empty())
389 .count();
390
391 self.bits.truncate(last_set_bit_index);
392 self.bits.shrink_to_fit();
393 }
394}
395
396macro_rules! growable_bitmap_storage_integer_tests {
397 ($(($int: ty, $mod_name: ident))*) => {
398 $(
399 #[cfg(test)]
400 mod $mod_name {
401 use super::*;
402
403 #[test]
404 fn new() {
405 let bm = GrowableBitMap::<$int>::new();
406 let bm2 = GrowableBitMap {
407 bits: Vec::<$int>::new(),
408 };
409
410 assert_eq!(bm, bm2);
411 }
412
413 #[test]
414 fn with_capacity() {
415 let bm = GrowableBitMap::<$int>::with_capacity(0);
416 let vec = Vec::<$int>::with_capacity(0);
417 assert_eq!(bm.bits.capacity(), vec.capacity());
418
419 let bm = GrowableBitMap::<$int>::with_capacity(11);
420 let vec = Vec::<$int>::with_capacity(11);
421 assert!(bm.bits.capacity() >= vec.capacity() / <$int>::BITS_IN_STORAGE);
422 }
423
424 #[test]
425 fn is_empty() {
426 let bm = GrowableBitMap::<$int>::new();
427 assert!(bm.is_empty());
428
429 let mut bm = GrowableBitMap::<$int>::with_capacity(3);
430 assert!(bm.is_empty());
431
432 bm.set_bit(7);
433 assert!(!bm.is_empty());
434
435 bm.clear_bit(7);
436 assert!(bm.is_empty());
437
438 bm.set_bit(7);
439 bm.set_bit(3);
440 bm.set_bit(4);
441 assert!(!bm.is_empty());
442
443 bm.clear();
444 assert!(bm.is_empty());
445 }
446
447 #[test]
448 fn get_bit() {
449 let bm = GrowableBitMap::<$int>::new();
450
451 assert!(!bm.get_bit(0));
452 assert!(!bm.get_bit(7));
453
454 // Ensuring `get_bit` does not allocate.
455 let old_capa = bm.capacity();
456 assert!(!bm.get_bit(200000003));
457 assert_eq!(old_capa, bm.capacity());
458
459 let mut bm = bm;
460 bm.set_bit(0);
461 bm.set_bit(6);
462
463 assert!(bm.get_bit(0));
464 assert!(bm.get_bit(6));
465
466 // Still false.
467 assert!(!bm.get_bit(7));
468 assert!(!bm.get_bit(3));
469 }
470
471 #[test]
472 fn set_bit() {
473 let mut bm = GrowableBitMap::<$int>::new();
474
475 assert!(bm.set_bit(0));
476 assert!(bm.set_bit(7));
477
478 assert!(!bm.set_bit(0));
479
480 // Ensuring `set_bit` does allocate when necessary.
481 let old_capa = bm.capacity();
482 assert!(bm.set_bit(150));
483 assert!(old_capa <= bm.capacity());
484 assert!(bm.get_bit(150));
485 }
486
487 #[test]
488 fn clear_bit() {
489 let mut bm = GrowableBitMap::<$int>::new();
490
491 assert!(!bm.clear_bit(0));
492 assert!(!bm.clear_bit(7));
493
494 bm.set_bit(0);
495 assert!(bm.clear_bit(0));
496
497 // Ensuring `clear_bit` does not allocate nor free.
498 let old_capa = bm.capacity();
499 assert!(!bm.clear_bit(200000003));
500 assert_eq!(old_capa, bm.capacity());
501
502 bm.set_bit(150);
503 assert!(bm.clear_bit(150));
504
505 assert!(bm.is_empty());
506 }
507
508 #[test]
509 fn clear() {
510 let mut bm = GrowableBitMap::<$int>::new();
511
512 bm.clear();
513 assert!(bm.is_empty());
514
515 bm.set_bit(253);
516 // Ensuring `clear_bit` does not allocate nor free.
517 let old_capa = bm.capacity();
518 bm.clear();
519 assert_eq!(old_capa, bm.capacity());
520
521 bm.set_bit(30);
522 bm.set_bit(4);
523
524 bm.clear();
525 assert!(bm.is_empty());
526 }
527
528 #[test]
529 fn count_ones() {
530 let mut bm = GrowableBitMap::<$int>::new();
531 assert_eq!(bm.count_ones(), 0);
532
533 bm.set_bit(0);
534 assert_eq!(bm.count_ones(), 1);
535
536 bm.set_bit(30);
537 assert_eq!(bm.count_ones(), 2);
538
539 bm.set_bit(7);
540 assert_eq!(bm.count_ones(), 3);
541
542 bm.clear_bit(0);
543 assert_eq!(bm.count_ones(), 2);
544
545 bm.clear();
546 assert_eq!(bm.count_ones(), 0);
547 }
548
549 #[test]
550 fn capacity() {
551 let mut bm = GrowableBitMap::<$int>::new();
552 assert_eq!(bm.capacity(), 0);
553
554 bm.set_bit(511);
555 assert_eq!(bm.capacity(), 512);
556 }
557
558 #[test]
559 fn shrink_to_fit() {
560 let mut bm = GrowableBitMap::<$int>::with_capacity(381);
561 bm.set_bit(127);
562 bm.set_bit(380);
563 assert_eq!(bm.capacity(), 384);
564
565 bm.clear_bit(380);
566 bm.shrink_to_fit();
567 assert_eq!(bm.capacity(), 128);
568 }
569 }
570 )*
571 }
572}
573
574growable_bitmap_storage_integer_tests! {
575 (u8, test_u8)
576 (u16, test_u16)
577 (u32, test_u32)
578 (u64, test_u64)
579 (u128, test_u128)
580}