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}