Skip to main content

commonware_utils/bitmap/
mod.rs

1//! Bitmap implementation
2//!
3//! The bitmap is a compact representation of a sequence of bits, using chunks of bytes for a
4//! more-efficient memory layout than doing [`Vec<bool>`].
5
6#[cfg(not(feature = "std"))]
7use alloc::{collections::VecDeque, vec::Vec};
8use bytes::{Buf, BufMut};
9use commonware_codec::{util::at_least, EncodeSize, Error as CodecError, Read, ReadExt, Write};
10use core::{
11    fmt::{self, Formatter, Write as _},
12    iter,
13    ops::{BitAnd, BitOr, BitXor, Index, Range},
14};
15#[cfg(feature = "std")]
16use std::collections::VecDeque;
17
18mod prunable;
19pub use prunable::Prunable;
20
21pub mod historical;
22commonware_macros::stability_mod!(ALPHA, pub mod roaring);
23
24/// The default [BitMap] chunk size in bytes.
25pub const DEFAULT_CHUNK_SIZE: usize = 8;
26
27/// A bitmap that stores data in chunks of N bytes.
28///
29/// # Panics
30///
31/// Operations panic if `bit / CHUNK_SIZE_BITS > usize::MAX`. On 32-bit systems
32/// with N=32, this occurs at bit >= 1,099,511,627,776.
33#[derive(Clone, PartialEq, Eq, Hash)]
34pub struct BitMap<const N: usize = DEFAULT_CHUNK_SIZE> {
35    /// The bitmap itself, in chunks of size N bytes. Within each byte, lowest order bits are
36    /// treated as coming before higher order bits in the bit ordering.
37    ///
38    /// Invariant: `chunks.len() == len.div_ceil(CHUNK_SIZE_BITS)`
39    /// Invariant: All bits at index `i` where `i >= len` must be 0.
40    chunks: VecDeque<[u8; N]>,
41
42    /// The total number of bits stored in the bitmap.
43    len: u64,
44}
45
46impl<const N: usize> BitMap<N> {
47    const _CHUNK_SIZE_NON_ZERO_ASSERT: () = assert!(N > 0, "chunk size must be > 0");
48
49    /// The size of a chunk in bits.
50    pub const CHUNK_SIZE_BITS: u64 = (N * 8) as u64;
51
52    /// A chunk of all 0s.
53    const EMPTY_CHUNK: [u8; N] = [0u8; N];
54
55    /// A chunk of all 1s.
56    const FULL_CHUNK: [u8; N] = [u8::MAX; N];
57
58    /* Constructors */
59
60    /// Create a new empty bitmap.
61    pub const fn new() -> Self {
62        #[allow(path_statements)]
63        Self::_CHUNK_SIZE_NON_ZERO_ASSERT; // Prevent compilation for N == 0
64
65        Self {
66            chunks: VecDeque::new(),
67            len: 0,
68        }
69    }
70
71    // Create a new empty bitmap with the capacity to hold `size` bits without reallocating.
72    pub fn with_capacity(size: u64) -> Self {
73        #[allow(path_statements)]
74        Self::_CHUNK_SIZE_NON_ZERO_ASSERT; // Prevent compilation for N == 0
75
76        Self {
77            chunks: VecDeque::with_capacity(size.div_ceil(Self::CHUNK_SIZE_BITS) as usize),
78            len: 0,
79        }
80    }
81
82    /// Create a new bitmap with `size` bits, with all bits set to 0.
83    pub fn zeroes(size: u64) -> Self {
84        #[allow(path_statements)]
85        Self::_CHUNK_SIZE_NON_ZERO_ASSERT; // Prevent compilation for N == 0
86
87        let num_chunks = size.div_ceil(Self::CHUNK_SIZE_BITS) as usize;
88        let mut chunks = VecDeque::with_capacity(num_chunks);
89        for _ in 0..num_chunks {
90            chunks.push_back(Self::EMPTY_CHUNK);
91        }
92        Self { chunks, len: size }
93    }
94
95    /// Create a new bitmap with `size` bits, with all bits set to 1.
96    pub fn ones(size: u64) -> Self {
97        #[allow(path_statements)]
98        Self::_CHUNK_SIZE_NON_ZERO_ASSERT; // Prevent compilation for N == 0
99
100        let num_chunks = size.div_ceil(Self::CHUNK_SIZE_BITS) as usize;
101        let mut chunks = VecDeque::with_capacity(num_chunks);
102        for _ in 0..num_chunks {
103            chunks.push_back(Self::FULL_CHUNK);
104        }
105        let mut result = Self { chunks, len: size };
106        // Clear trailing bits to maintain invariant
107        result.clear_trailing_bits();
108        result
109    }
110
111    /* Length */
112
113    /// Return the number of bits currently stored in the bitmap.
114    #[inline]
115    pub const fn len(&self) -> u64 {
116        self.len
117    }
118
119    /// Returns true if the bitmap is empty.
120    #[inline]
121    pub const fn is_empty(&self) -> bool {
122        self.len() == 0
123    }
124
125    /// Returns true if the bitmap length is aligned to a chunk boundary.
126    #[inline]
127    pub const fn is_chunk_aligned(&self) -> bool {
128        self.len.is_multiple_of(Self::CHUNK_SIZE_BITS)
129    }
130
131    // Get the number of chunks currently in the bitmap.
132    fn chunks_len(&self) -> usize {
133        self.chunks.len()
134    }
135
136    /* Getters */
137
138    /// Get the value of the bit at the given index.
139    ///
140    /// # Warning
141    ///
142    /// Panics if the bit doesn't exist.
143    #[inline]
144    pub fn get(&self, bit: u64) -> bool {
145        let chunk = self.get_chunk_containing(bit);
146        Self::get_bit_from_chunk(chunk, bit)
147    }
148
149    /// Returns the bitmap chunk containing the given bit.
150    ///
151    /// # Warning
152    ///
153    /// Panics if the bit doesn't exist.
154    #[inline]
155    fn get_chunk_containing(&self, bit: u64) -> &[u8; N] {
156        assert!(
157            bit < self.len(),
158            "bit {} out of bounds (len: {})",
159            bit,
160            self.len()
161        );
162        &self.chunks[Self::to_chunk_index(bit)]
163    }
164
165    /// Get a reference to a chunk by its index in the current bitmap.
166    /// Note this is an index into the chunks, not a bit.
167    ///
168    /// # Warning
169    ///
170    /// Panics if the `chunk` is out of bounds.
171    #[inline]
172    pub(super) fn get_chunk(&self, chunk: usize) -> &[u8; N] {
173        assert!(
174            chunk < self.chunks.len(),
175            "chunk {} out of bounds (chunks: {})",
176            chunk,
177            self.chunks.len()
178        );
179        &self.chunks[chunk]
180    }
181
182    /// Get the value at the given `bit` from the `chunk`.
183    /// `bit` is an index into the entire bitmap, not just the chunk.
184    #[inline]
185    pub const fn get_bit_from_chunk(chunk: &[u8; N], bit: u64) -> bool {
186        let byte = Self::chunk_byte_offset(bit);
187        let byte = chunk[byte];
188        let mask = Self::chunk_byte_bitmask(bit);
189        (byte & mask) != 0
190    }
191
192    /// Return the last chunk of the bitmap and its size in bits.
193    ///
194    /// # Panics
195    ///
196    /// Panics if bitmap is empty.
197    #[inline]
198    fn last_chunk(&self) -> (&[u8; N], u64) {
199        let rem = self.len % Self::CHUNK_SIZE_BITS;
200        let bits_in_last_chunk = if rem == 0 { Self::CHUNK_SIZE_BITS } else { rem };
201        (self.chunks.back().unwrap(), bits_in_last_chunk)
202    }
203
204    /* Setters */
205
206    /// Extend the bitmap to `new_len` bits, filling new positions with zero.
207    /// No-op if `new_len <= self.len`.
208    pub fn extend_to(&mut self, new_len: u64) {
209        if new_len <= self.len {
210            return;
211        }
212        // Allocate any needed new chunks (all zeroed).
213        let new_chunks_needed = new_len.div_ceil(Self::CHUNK_SIZE_BITS) as usize;
214        let current_chunks = self.chunks.len();
215        for _ in current_chunks..new_chunks_needed {
216            self.chunks.push_back(Self::EMPTY_CHUNK);
217        }
218        self.len = new_len;
219    }
220
221    /// Add a single bit to the bitmap.
222    pub fn push(&mut self, bit: bool) {
223        // Check if we need a new chunk
224        if self.is_chunk_aligned() {
225            self.chunks.push_back(Self::EMPTY_CHUNK);
226        }
227
228        // Append to the last chunk
229        if bit {
230            let last_chunk = self.chunks.back_mut().unwrap();
231            let chunk_byte = Self::chunk_byte_offset(self.len);
232            last_chunk[chunk_byte] |= Self::chunk_byte_bitmask(self.len);
233        }
234        // If bit is false, just advance len -- the bit is already 0
235        self.len += 1;
236    }
237
238    /// Remove and return the last bit from the bitmap.
239    ///
240    /// # Warning
241    ///
242    /// Panics if the bitmap is empty.
243    pub fn pop(&mut self) -> bool {
244        assert!(!self.is_empty(), "Cannot pop from empty bitmap");
245
246        // Get the bit value at the last position
247        let last_bit_pos = self.len - 1;
248        let bit = Self::get_bit_from_chunk(self.chunks.back().unwrap(), last_bit_pos);
249
250        // Decrement length
251        self.len -= 1;
252
253        // Clear the bit we just popped to maintain invariant (if it was 1)
254        if bit {
255            let chunk_byte = Self::chunk_byte_offset(last_bit_pos);
256            let mask = Self::chunk_byte_bitmask(last_bit_pos);
257            self.chunks.back_mut().unwrap()[chunk_byte] &= !mask;
258        }
259
260        // Remove the last chunk if it's now empty
261        if self.is_chunk_aligned() {
262            self.chunks.pop_back();
263        }
264
265        bit
266    }
267
268    /// Shrink the bitmap to `new_len` bits, discarding trailing bits.
269    ///
270    /// # Panics
271    ///
272    /// Panics if `new_len > self.len()`.
273    pub fn truncate(&mut self, new_len: u64) {
274        assert!(new_len <= self.len(), "cannot truncate to a larger size");
275
276        // Pop single bits until we can remove full chunks.
277        while self.len > new_len && !self.is_chunk_aligned() {
278            self.pop();
279        }
280
281        // Pop full chunks from the back.
282        while self.len - new_len >= Self::CHUNK_SIZE_BITS {
283            self.pop_chunk();
284        }
285
286        // Pop remaining individual bits.
287        while self.len > new_len {
288            self.pop();
289        }
290    }
291
292    /// Remove and return the last complete chunk from the bitmap.
293    ///
294    /// # Warning
295    ///
296    /// Panics if the bitmap has fewer than `CHUNK_SIZE_BITS` bits or if not chunk-aligned.
297    pub(super) fn pop_chunk(&mut self) -> [u8; N] {
298        assert!(
299            self.len() >= Self::CHUNK_SIZE_BITS,
300            "cannot pop chunk: bitmap has fewer than CHUNK_SIZE_BITS bits"
301        );
302        assert!(
303            self.is_chunk_aligned(),
304            "cannot pop chunk when not chunk aligned"
305        );
306
307        // Remove and return the last data chunk
308        let chunk = self.chunks.pop_back().expect("chunk must exist");
309        self.len -= Self::CHUNK_SIZE_BITS;
310        chunk
311    }
312
313    /// Flips the given bit.
314    ///
315    /// # Panics
316    ///
317    /// Panics if `bit` is out of bounds.
318    #[inline]
319    pub fn flip(&mut self, bit: u64) {
320        self.assert_bit(bit);
321        let chunk = Self::to_chunk_index(bit);
322        let byte = Self::chunk_byte_offset(bit);
323        let mask = Self::chunk_byte_bitmask(bit);
324        self.chunks[chunk][byte] ^= mask;
325    }
326
327    /// Flips all bits (1s become 0s and vice versa).
328    pub fn flip_all(&mut self) {
329        for chunk in &mut self.chunks {
330            for byte in chunk {
331                *byte = !*byte;
332            }
333        }
334        // Clear trailing bits to maintain invariant
335        self.clear_trailing_bits();
336    }
337
338    /// Set the value of the referenced bit.
339    ///
340    /// # Warning
341    ///
342    /// Panics if the bit doesn't exist.
343    pub fn set(&mut self, bit: u64, value: bool) {
344        assert!(
345            bit < self.len(),
346            "bit {} out of bounds (len: {})",
347            bit,
348            self.len()
349        );
350
351        let chunk = &mut self.chunks[Self::to_chunk_index(bit)];
352        let byte = Self::chunk_byte_offset(bit);
353        let mask = Self::chunk_byte_bitmask(bit);
354        if value {
355            chunk[byte] |= mask;
356        } else {
357            chunk[byte] &= !mask;
358        }
359    }
360
361    /// Sets all bits to the specified value.
362    #[inline]
363    pub fn set_all(&mut self, bit: bool) {
364        let value = if bit { u8::MAX } else { 0 };
365        for chunk in &mut self.chunks {
366            chunk.fill(value);
367        }
368        // Clear trailing bits to maintain invariant
369        if bit {
370            self.clear_trailing_bits();
371        }
372    }
373
374    // Add a byte's worth of bits to the bitmap.
375    //
376    // # Warning
377    //
378    // Panics if self.len is not byte aligned.
379    fn push_byte(&mut self, byte: u8) {
380        assert!(
381            self.len.is_multiple_of(8),
382            "cannot add byte when not byte aligned"
383        );
384
385        // Check if we need a new chunk
386        if self.is_chunk_aligned() {
387            self.chunks.push_back(Self::EMPTY_CHUNK);
388        }
389
390        let chunk_byte = Self::chunk_byte_offset(self.len);
391        self.chunks.back_mut().unwrap()[chunk_byte] = byte;
392        self.len += 8;
393    }
394
395    /// Add a chunk of bits to the bitmap.
396    ///
397    /// # Warning
398    ///
399    /// Panics if self.len is not chunk aligned.
400    pub fn push_chunk(&mut self, chunk: &[u8; N]) {
401        assert!(
402            self.is_chunk_aligned(),
403            "cannot add chunk when not chunk aligned"
404        );
405        self.chunks.push_back(*chunk);
406        self.len += Self::CHUNK_SIZE_BITS;
407    }
408
409    /* Invariant Maintenance */
410
411    /// Clear all bits in the last chunk that are >= self.len to maintain the invariant.
412    /// Returns true if any bits were flipped from 1 to 0.
413    fn clear_trailing_bits(&mut self) -> bool {
414        if self.chunks.is_empty() {
415            return false;
416        }
417
418        let pos_in_chunk = self.len % Self::CHUNK_SIZE_BITS;
419        if pos_in_chunk == 0 {
420            // Chunk is full -- there are no trailing bits to clear.
421            return false;
422        }
423
424        let mut flipped_any = false;
425        let last_chunk = self.chunks.back_mut().unwrap();
426
427        // Clear whole bytes after the last valid bit
428        let last_byte_index = ((pos_in_chunk - 1) / 8) as usize;
429        for byte in last_chunk.iter_mut().skip(last_byte_index + 1) {
430            if *byte != 0 {
431                flipped_any = true;
432                *byte = 0;
433            }
434        }
435
436        // Clear the trailing bits in the last partial byte
437        let bits_in_last_byte = pos_in_chunk % 8;
438        if bits_in_last_byte != 0 {
439            let mask = (1u8 << bits_in_last_byte) - 1;
440            let old_byte = last_chunk[last_byte_index];
441            let new_byte = old_byte & mask;
442            if old_byte != new_byte {
443                flipped_any = true;
444                last_chunk[last_byte_index] = new_byte;
445            }
446        }
447
448        flipped_any
449    }
450
451    /* Pruning */
452
453    /// Remove the first `chunks` chunks from the bitmap.
454    ///
455    /// # Warning
456    ///
457    /// Panics if trying to prune more chunks than exist.
458    fn prune_chunks(&mut self, chunks: usize) {
459        assert!(
460            chunks <= self.chunks.len(),
461            "cannot prune {chunks} chunks, only {} available",
462            self.chunks.len()
463        );
464        self.chunks.drain(..chunks);
465        // Update len to reflect the removed chunks
466        let bits_removed = (chunks as u64) * Self::CHUNK_SIZE_BITS;
467        self.len = self.len.saturating_sub(bits_removed);
468    }
469
470    /// Prepend a chunk to the beginning of the bitmap.
471    pub(super) fn prepend_chunk(&mut self, chunk: &[u8; N]) {
472        self.chunks.push_front(*chunk);
473        self.len += Self::CHUNK_SIZE_BITS;
474    }
475
476    /// Overwrite a chunk's data at the given index.
477    ///
478    /// Replaces the entire chunk data, including any bits beyond `len()` in the last chunk.
479    /// The caller is responsible for ensuring `chunk_data` has the correct bit pattern
480    /// (e.g., zeros beyond the valid length if this is a partial last chunk).
481    ///
482    /// # Panics
483    ///
484    /// Panics if chunk_index is out of bounds.
485    pub(super) fn set_chunk_by_index(&mut self, chunk_index: usize, chunk_data: &[u8; N]) {
486        assert!(
487            chunk_index < self.chunks.len(),
488            "chunk index {chunk_index} out of bounds (chunks_len: {})",
489            self.chunks.len()
490        );
491        self.chunks[chunk_index].copy_from_slice(chunk_data);
492    }
493
494    /* Counting */
495
496    /// Returns the number of bits set to 1.
497    #[inline]
498    pub fn count_ones(&self) -> u64 {
499        // Thanks to the invariant that trailing bits are always 0,
500        // we can simply count all set bits in all chunks.
501        // Iterate over both contiguous deque segments and count 64-bit words first.
502        let (front, back) = self.chunks.as_slices();
503        Self::count_ones_in_chunk_slice(front) + Self::count_ones_in_chunk_slice(back)
504    }
505
506    #[inline]
507    fn count_ones_in_chunk_slice(chunks: &[[u8; N]]) -> u64 {
508        let mut total = 0u64;
509        let mut words = chunks.as_flattened().chunks_exact(8);
510        for word in &mut words {
511            total += u64::from_le_bytes(word.try_into().unwrap()).count_ones() as u64;
512        }
513        for byte in words.remainder() {
514            total += byte.count_ones() as u64;
515        }
516        total
517    }
518
519    /// Returns the number of bits set to 0.
520    #[inline]
521    pub fn count_zeros(&self) -> u64 {
522        self.len() - self.count_ones()
523    }
524
525    /* Indexing Helpers */
526
527    /// Convert a bit offset into a bitmask for the byte containing that bit.
528    #[inline]
529    pub(super) const fn chunk_byte_bitmask(bit: u64) -> u8 {
530        1 << (bit % 8)
531    }
532
533    /// Convert a bit into the index of the byte within a chunk containing the bit.
534    #[inline]
535    pub(super) const fn chunk_byte_offset(bit: u64) -> usize {
536        ((bit / 8) % N as u64) as usize
537    }
538
539    /// Convert a bit into the index of the chunk it belongs to.
540    ///
541    /// # Panics
542    ///
543    /// Panics if the chunk index overflows `usize`.
544    #[inline]
545    pub(super) fn to_chunk_index(bit: u64) -> usize {
546        let chunk = bit / Self::CHUNK_SIZE_BITS;
547        assert!(
548            chunk <= usize::MAX as u64,
549            "chunk overflow: {chunk} exceeds usize::MAX",
550        );
551        chunk as usize
552    }
553
554    /* Iterator */
555
556    /// Creates an iterator over the bits.
557    pub const fn iter(&self) -> Iterator<'_, N> {
558        Iterator {
559            bitmap: self,
560            pos: 0,
561        }
562    }
563
564    /// Returns an iterator over the indices of set bits.
565    pub fn ones_iter(&self) -> OnesIter<'_, Self, N> {
566        Readable::ones_iter_from(self, 0)
567    }
568
569    /* Bitwise Operations */
570
571    /// Helper for binary operations
572    #[inline]
573    fn binary_op<F: Fn(u8, u8) -> u8>(&mut self, other: &Self, op: F) {
574        self.assert_eq_len(other);
575        for (a_chunk, b_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
576            for (a_byte, b_byte) in a_chunk.iter_mut().zip(b_chunk.iter()) {
577                *a_byte = op(*a_byte, *b_byte);
578            }
579        }
580        // Clear trailing bits to maintain invariant
581        self.clear_trailing_bits();
582    }
583
584    /// Performs a bitwise AND with another BitMap.
585    ///
586    /// # Panics
587    ///
588    /// Panics if the lengths don't match.
589    pub fn and(&mut self, other: &Self) {
590        self.binary_op(other, |a, b| a & b);
591    }
592
593    /// Performs a bitwise OR with another BitMap.
594    ///
595    /// # Panics
596    ///
597    /// Panics if the lengths don't match.
598    pub fn or(&mut self, other: &Self) {
599        self.binary_op(other, |a, b| a | b);
600    }
601
602    /// Performs a bitwise XOR with another BitMap.
603    ///
604    /// # Panics
605    ///
606    /// Panics if the lengths don't match.
607    pub fn xor(&mut self, other: &Self) {
608        self.binary_op(other, |a, b| a ^ b);
609    }
610
611    /* Assertions */
612
613    /// Asserts that the bit is within bounds.
614    #[inline(always)]
615    fn assert_bit(&self, bit: u64) {
616        assert!(
617            bit < self.len(),
618            "bit {} out of bounds (len: {})",
619            bit,
620            self.len()
621        );
622    }
623
624    /// Asserts that the lengths of two [BitMap]s match.
625    #[inline(always)]
626    fn assert_eq_len(&self, other: &Self) {
627        assert_eq!(
628            self.len(),
629            other.len(),
630            "BitMap lengths don't match: {} vs {}",
631            self.len(),
632            other.len()
633        );
634    }
635
636    /// Check if all the bits in a given range are 0.
637    ///
638    /// Returns `true` if every index in the range is unset (i.e.
639    /// [`Self::get`] returns `false`). Returns `true` if the range
640    /// is empty.
641    ///
642    /// # Panics
643    ///
644    /// Panics if `range.end` exceeds the length of the bitmap.
645    ///
646    /// # Examples
647    ///
648    /// ```
649    /// use commonware_utils::bitmap::BitMap;
650    ///
651    /// let mut bitmap = BitMap::<8>::zeroes(128);
652    /// assert!(bitmap.is_unset(0..128));
653    ///
654    /// bitmap.set(64, true);
655    /// assert!(bitmap.is_unset(0..64));
656    /// assert!(!bitmap.is_unset(0..65));
657    /// ```
658    pub fn is_unset(&self, range: Range<u64>) -> bool {
659        assert!(
660            range.end <= self.len(),
661            "range end {} out of bounds (len: {})",
662            range.end,
663            self.len()
664        );
665        if range.start >= range.end {
666            return true;
667        }
668        let start = range.start;
669        let end = range.end;
670
671        // We know this can't underflow, because start < end.
672        //
673        // We now want "end" to represent the last bit we want to consider.
674        let end = end - 1;
675
676        // Get the chunks containing the start and end bits.
677        let first_chunk = Self::to_chunk_index(start);
678        let last_chunk = Self::to_chunk_index(end);
679
680        // All of these chunks require all of their bits to be checked.
681        // If first_chunk == last_chunk, we skip the loop.
682        let zero = [0u8; N];
683        for full_chunk in (first_chunk + 1)..last_chunk {
684            if self.chunks[full_chunk] != zero {
685                return false;
686            }
687        }
688
689        // Check first chunk tail (or whole range if first_chunk == last_chunk).
690        let start_byte = Self::chunk_byte_offset(start);
691        let end_byte = Self::chunk_byte_offset(end);
692        let start_mask = (0xFFu16 << ((start & 0b111) as u32)) as u8;
693        let end_mask = (0xFFu16 >> (7 - ((end & 0b111) as u32))) as u8;
694        let first = &self.chunks[first_chunk];
695        let first_end_byte = if first_chunk == last_chunk {
696            end_byte
697        } else {
698            N - 1
699        };
700        for (i, &byte) in first
701            .iter()
702            .enumerate()
703            .take(first_end_byte + 1)
704            .skip(start_byte)
705        {
706            let mut mask = 0xFFu8;
707            if i == start_byte {
708                mask &= start_mask;
709            }
710            if first_chunk == last_chunk && i == end_byte {
711                mask &= end_mask;
712            }
713            if (byte & mask) != 0 {
714                return false;
715            }
716        }
717        if first_chunk == last_chunk {
718            return true;
719        }
720
721        // Check last chunk head.
722        let last = &self.chunks[last_chunk];
723        for (i, &byte) in last.iter().enumerate().take(end_byte + 1) {
724            let mask = if i == end_byte { end_mask } else { 0xFF };
725            if (byte & mask) != 0 {
726                return false;
727            }
728        }
729
730        true
731    }
732}
733
734impl<const N: usize> Default for BitMap<N> {
735    fn default() -> Self {
736        Self::new()
737    }
738}
739
740impl<T: AsRef<[bool]>, const N: usize> From<T> for BitMap<N> {
741    fn from(t: T) -> Self {
742        let bools = t.as_ref();
743        let mut bv = Self::with_capacity(bools.len() as u64);
744        for &b in bools {
745            bv.push(b);
746        }
747        bv
748    }
749}
750
751impl<const N: usize> From<BitMap<N>> for Vec<bool> {
752    fn from(bv: BitMap<N>) -> Self {
753        bv.iter().collect()
754    }
755}
756
757impl<const N: usize> fmt::Debug for BitMap<N> {
758    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
759        // For very large BitMaps, only show a preview
760        const MAX_DISPLAY: u64 = 64;
761        const HALF_DISPLAY: u64 = MAX_DISPLAY / 2;
762
763        // Closure for writing a bit
764        let write_bit = |formatter: &mut Formatter<'_>, bit: u64| -> core::fmt::Result {
765            formatter.write_char(if self.get(bit) { '1' } else { '0' })
766        };
767
768        f.write_str("BitMap[")?;
769        let len = self.len();
770        if len <= MAX_DISPLAY {
771            // Show all bits
772            for i in 0..len {
773                write_bit(f, i)?;
774            }
775        } else {
776            // Show first and last bits with ellipsis
777            for i in 0..HALF_DISPLAY {
778                write_bit(f, i)?;
779            }
780
781            f.write_str("...")?;
782
783            for i in (len - HALF_DISPLAY)..len {
784                write_bit(f, i)?;
785            }
786        }
787        f.write_str("]")
788    }
789}
790
791impl<const N: usize> Index<u64> for BitMap<N> {
792    type Output = bool;
793
794    /// Allows accessing bits using the `[]` operator.
795    ///
796    /// Panics if out of bounds.
797    #[inline]
798    fn index(&self, bit: u64) -> &Self::Output {
799        self.assert_bit(bit);
800        let value = self.get(bit);
801        if value {
802            &true
803        } else {
804            &false
805        }
806    }
807}
808
809impl<const N: usize> BitAnd for &BitMap<N> {
810    type Output = BitMap<N>;
811
812    fn bitand(self, rhs: Self) -> Self::Output {
813        self.assert_eq_len(rhs);
814        let mut result = self.clone();
815        result.and(rhs);
816        result
817    }
818}
819
820impl<const N: usize> BitOr for &BitMap<N> {
821    type Output = BitMap<N>;
822
823    fn bitor(self, rhs: Self) -> Self::Output {
824        self.assert_eq_len(rhs);
825        let mut result = self.clone();
826        result.or(rhs);
827        result
828    }
829}
830
831impl<const N: usize> BitXor for &BitMap<N> {
832    type Output = BitMap<N>;
833
834    fn bitxor(self, rhs: Self) -> Self::Output {
835        self.assert_eq_len(rhs);
836        let mut result = self.clone();
837        result.xor(rhs);
838        result
839    }
840}
841
842impl<const N: usize> Write for BitMap<N> {
843    fn write(&self, buf: &mut impl BufMut) {
844        // Prefix with the number of bits
845        self.len().write(buf);
846
847        // Write all chunks
848        let (front, back) = self.chunks.as_slices();
849        buf.put_slice(front.as_flattened());
850        buf.put_slice(back.as_flattened());
851    }
852}
853
854impl<const N: usize> Read for BitMap<N> {
855    type Cfg = u64; // Max bitmap length
856
857    fn read_cfg(buf: &mut impl Buf, max_len: &Self::Cfg) -> Result<Self, CodecError> {
858        // Parse length in bits
859        let len = u64::read(buf)?;
860        if len > *max_len {
861            return Err(CodecError::InvalidLength(len as usize));
862        }
863
864        // Calculate how many chunks we need to read
865        let num_chunks = len.div_ceil(Self::CHUNK_SIZE_BITS) as usize;
866
867        // Parse chunks
868        let mut chunks = VecDeque::with_capacity(num_chunks);
869        for _ in 0..num_chunks {
870            at_least(buf, N)?;
871            let mut chunk = [0u8; N];
872            buf.copy_to_slice(&mut chunk);
873            chunks.push_back(chunk);
874        }
875
876        let mut result = Self { chunks, len };
877
878        // Verify trailing bits are zero (maintain invariant)
879        if result.clear_trailing_bits() {
880            return Err(CodecError::Invalid(
881                "BitMap",
882                "Invalid trailing bits in encoded data",
883            ));
884        }
885
886        Ok(result)
887    }
888}
889
890impl<const N: usize> EncodeSize for BitMap<N> {
891    fn encode_size(&self) -> usize {
892        // Size of length prefix + all chunks
893        self.len().encode_size() + (self.chunks.len() * N)
894    }
895}
896
897/// Iterator over bits in a [BitMap].
898pub struct Iterator<'a, const N: usize> {
899    /// Reference to the BitMap being iterated over
900    bitmap: &'a BitMap<N>,
901
902    /// Current index in the BitMap
903    pos: u64,
904}
905
906impl<const N: usize> iter::Iterator for Iterator<'_, N> {
907    type Item = bool;
908
909    fn next(&mut self) -> Option<Self::Item> {
910        if self.pos >= self.bitmap.len() {
911            return None;
912        }
913
914        let bit = self.bitmap.get(self.pos);
915        self.pos += 1;
916        Some(bit)
917    }
918
919    fn size_hint(&self) -> (usize, Option<usize>) {
920        let remaining = self.bitmap.len().saturating_sub(self.pos);
921        let capped = remaining.min(usize::MAX as u64) as usize;
922        (capped, Some(capped))
923    }
924}
925
926impl<const N: usize> ExactSizeIterator for Iterator<'_, N> {}
927
928/// Read-only access to a bitmap's chunks and metadata.
929pub trait Readable<const N: usize> {
930    /// Return the number of complete (fully filled) chunks.
931    fn complete_chunks(&self) -> usize;
932
933    /// Return the chunk data at the given absolute chunk index.
934    fn get_chunk(&self, chunk: usize) -> [u8; N];
935
936    /// Return the last chunk and its size in bits.
937    fn last_chunk(&self) -> ([u8; N], u64);
938
939    /// Return the number of pruned chunks.
940    fn pruned_chunks(&self) -> usize;
941
942    /// Return the total number of bits.
943    fn len(&self) -> u64;
944
945    /// Returns true if the bitmap is empty.
946    fn is_empty(&self) -> bool {
947        self.len() == 0
948    }
949
950    /// Return the number of pruned bits (i.e. pruned chunks * bits per chunk).
951    fn pruned_bits(&self) -> u64 {
952        (self.pruned_chunks() as u64) * BitMap::<N>::CHUNK_SIZE_BITS
953    }
954
955    /// Return the value of a single bit.
956    fn get_bit(&self, bit: u64) -> bool {
957        let chunk = self.get_chunk(BitMap::<N>::to_chunk_index(bit));
958        BitMap::<N>::get_bit_from_chunk(&chunk, bit % BitMap::<N>::CHUNK_SIZE_BITS)
959    }
960
961    /// Returns an iterator over the indices of set bits starting from `pos`.
962    ///
963    /// If `pos` falls within a pruned region, iteration starts at the first
964    /// unpruned bit instead.
965    fn ones_iter_from(&self, pos: u64) -> OnesIter<'_, Self, N>
966    where
967        Self: Sized,
968    {
969        let len = self.len();
970        let pruned_start = (self.pruned_chunks() as u64) * BitMap::<N>::CHUNK_SIZE_BITS;
971        OnesIter {
972            bitmap: self,
973            pos: pos.max(pruned_start),
974            len,
975        }
976    }
977}
978
979impl<const N: usize> Readable<N> for BitMap<N> {
980    fn complete_chunks(&self) -> usize {
981        self.chunks_len()
982            .saturating_sub(if self.is_chunk_aligned() { 0 } else { 1 })
983    }
984
985    fn get_chunk(&self, chunk: usize) -> [u8; N] {
986        *Self::get_chunk(self, chunk)
987    }
988
989    fn last_chunk(&self) -> ([u8; N], u64) {
990        let (c, n) = Self::last_chunk(self);
991        (*c, n)
992    }
993
994    fn pruned_chunks(&self) -> usize {
995        0
996    }
997
998    fn len(&self) -> u64 {
999        self.len
1000    }
1001}
1002
1003/// Iterator over the indices of set (1) bits in a bitmap.
1004///
1005/// If the starting position falls within a pruned region, iteration
1006/// begins at the first unpruned bit.
1007pub struct OnesIter<'a, B, const N: usize> {
1008    bitmap: &'a B,
1009    pos: u64,
1010    /// Cached `bitmap.len()` at iterator construction. The underlying bitmap is borrowed
1011    /// immutably for the iterator's lifetime, so this can never change mid-iteration.
1012    /// For layered bitmaps (e.g. `BitmapBatch`), `len()` walks the layer chain, so caching
1013    /// this avoids that walk on every `next`.
1014    len: u64,
1015}
1016
1017impl<B: Readable<N>, const N: usize> iter::Iterator for OnesIter<'_, B, N> {
1018    type Item = u64;
1019
1020    fn next(&mut self) -> Option<u64> {
1021        let chunk_bits = BitMap::<N>::CHUNK_SIZE_BITS;
1022        while self.pos < self.len {
1023            let chunk_idx = BitMap::<N>::to_chunk_index(self.pos);
1024            let chunk = self.bitmap.get_chunk(chunk_idx);
1025            let chunk_start = chunk_idx as u64 * chunk_bits;
1026            let rel = (self.pos - chunk_start) as usize;
1027            let mut byte_idx = rel / 8;
1028            let mut bit_in_byte = rel % 8;
1029            while byte_idx < N {
1030                let masked = chunk[byte_idx] >> bit_in_byte;
1031                if masked != 0 {
1032                    let found = chunk_start
1033                        + (byte_idx * 8 + bit_in_byte) as u64
1034                        + masked.trailing_zeros() as u64;
1035                    if found >= self.len {
1036                        return None;
1037                    }
1038                    self.pos = found + 1;
1039                    return Some(found);
1040                }
1041                byte_idx += 1;
1042                bit_in_byte = 0;
1043            }
1044            self.pos = chunk_start + chunk_bits;
1045        }
1046        None
1047    }
1048}
1049
1050#[cfg(feature = "arbitrary")]
1051impl<const N: usize> arbitrary::Arbitrary<'_> for BitMap<N> {
1052    fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
1053        let size = u.int_in_range(0..=1024)?;
1054        let mut bits = Self::with_capacity(size);
1055        for _ in 0..size {
1056            bits.push(u.arbitrary::<bool>()?);
1057        }
1058        Ok(bits)
1059    }
1060}
1061
1062#[cfg(test)]
1063mod tests {
1064    use super::*;
1065    use bytes::BytesMut;
1066    use commonware_codec::{Decode, Encode};
1067    use commonware_formatting::hex;
1068
1069    #[test]
1070    fn test_constructors() {
1071        // Test new()
1072        let bv: BitMap<4> = BitMap::new();
1073        assert_eq!(bv.len(), 0);
1074        assert!(bv.is_empty());
1075
1076        // Test default()
1077        let bv: BitMap<4> = Default::default();
1078        assert_eq!(bv.len(), 0);
1079        assert!(bv.is_empty());
1080
1081        // Test with_capacity()
1082        let bv: BitMap<4> = BitMap::with_capacity(0);
1083        assert_eq!(bv.len(), 0);
1084        assert!(bv.is_empty());
1085
1086        let bv: BitMap<4> = BitMap::with_capacity(10);
1087        assert_eq!(bv.len(), 0);
1088        assert!(bv.is_empty());
1089    }
1090
1091    #[test]
1092    fn test_zeroes() {
1093        let bv: BitMap<1> = BitMap::zeroes(0);
1094        assert_eq!(bv.len(), 0);
1095        assert!(bv.is_empty());
1096        assert_eq!(bv.count_ones(), 0);
1097        assert_eq!(bv.count_zeros(), 0);
1098
1099        let bv: BitMap<1> = BitMap::zeroes(1);
1100        assert_eq!(bv.len(), 1);
1101        assert!(!bv.is_empty());
1102        assert_eq!(bv.len(), 1);
1103        assert!(!bv.get(0));
1104        assert_eq!(bv.count_ones(), 0);
1105        assert_eq!(bv.count_zeros(), 1);
1106
1107        let bv: BitMap<1> = BitMap::zeroes(10);
1108        assert_eq!(bv.len(), 10);
1109        assert!(!bv.is_empty());
1110        assert_eq!(bv.len(), 10);
1111        for i in 0..10 {
1112            assert!(!bv.get(i as u64));
1113        }
1114        assert_eq!(bv.count_ones(), 0);
1115        assert_eq!(bv.count_zeros(), 10);
1116    }
1117
1118    #[test]
1119    fn test_ones() {
1120        let bv: BitMap<1> = BitMap::ones(0);
1121        assert_eq!(bv.len(), 0);
1122        assert!(bv.is_empty());
1123        assert_eq!(bv.count_ones(), 0);
1124        assert_eq!(bv.count_zeros(), 0);
1125
1126        let bv: BitMap<1> = BitMap::ones(1);
1127        assert_eq!(bv.len(), 1);
1128        assert!(!bv.is_empty());
1129        assert_eq!(bv.len(), 1);
1130        assert!(bv.get(0));
1131        assert_eq!(bv.count_ones(), 1);
1132        assert_eq!(bv.count_zeros(), 0);
1133
1134        let bv: BitMap<1> = BitMap::ones(10);
1135        assert_eq!(bv.len(), 10);
1136        assert!(!bv.is_empty());
1137        assert_eq!(bv.len(), 10);
1138        for i in 0..10 {
1139            assert!(bv.get(i as u64));
1140        }
1141        assert_eq!(bv.count_ones(), 10);
1142        assert_eq!(bv.count_zeros(), 0);
1143    }
1144
1145    #[test]
1146    fn test_invariant_trailing_bits_are_zero() {
1147        // Helper function to check the invariant
1148        fn check_trailing_bits_zero<const N: usize>(bitmap: &BitMap<N>) {
1149            let (last_chunk, next_bit) = bitmap.last_chunk();
1150
1151            // Check that all bits >= next_bit in the last chunk are 0
1152            for bit_idx in next_bit..((N * 8) as u64) {
1153                let byte_idx = (bit_idx / 8) as usize;
1154                let bit_in_byte = bit_idx % 8;
1155                let mask = 1u8 << bit_in_byte;
1156                assert_eq!(last_chunk[byte_idx] & mask, 0);
1157            }
1158        }
1159
1160        // Test ones() constructor
1161        let bv: BitMap<4> = BitMap::ones(15);
1162        check_trailing_bits_zero(&bv);
1163
1164        let bv: BitMap<4> = BitMap::ones(33);
1165        check_trailing_bits_zero(&bv);
1166
1167        // Test after push operations
1168        let mut bv: BitMap<4> = BitMap::new();
1169        for i in 0..37 {
1170            bv.push(i % 2 == 0);
1171            check_trailing_bits_zero(&bv);
1172        }
1173
1174        // Test after pop operations
1175        let mut bv: BitMap<4> = BitMap::ones(40);
1176        check_trailing_bits_zero(&bv);
1177        for _ in 0..15 {
1178            bv.pop();
1179            check_trailing_bits_zero(&bv);
1180        }
1181
1182        // Test after flip_all
1183        let mut bv: BitMap<4> = BitMap::ones(25);
1184        bv.flip_all();
1185        check_trailing_bits_zero(&bv);
1186
1187        // Test after binary operations
1188        let bv1: BitMap<4> = BitMap::ones(20);
1189        let bv2: BitMap<4> = BitMap::zeroes(20);
1190
1191        let mut bv_and = bv1.clone();
1192        bv_and.and(&bv2);
1193        check_trailing_bits_zero(&bv_and);
1194
1195        let mut bv_or = bv1.clone();
1196        bv_or.or(&bv2);
1197        check_trailing_bits_zero(&bv_or);
1198
1199        let mut bv_xor = bv1;
1200        bv_xor.xor(&bv2);
1201        check_trailing_bits_zero(&bv_xor);
1202
1203        // Test after deserialization
1204        let original: BitMap<4> = BitMap::ones(27);
1205        let encoded = original.encode();
1206        let decoded: BitMap<4> =
1207            BitMap::decode_cfg(&mut encoded.as_ref(), &(usize::MAX as u64)).unwrap();
1208        check_trailing_bits_zero(&decoded);
1209
1210        // Test clear_trailing_bits return value
1211        let mut bv_clean: BitMap<4> = BitMap::ones(20);
1212        // Should return false since ones() already clears trailing bits
1213        assert!(!bv_clean.clear_trailing_bits());
1214
1215        // Create a bitmap with invalid trailing bits by manually setting them
1216        let mut bv_dirty: BitMap<4> = BitMap::ones(20);
1217        // Manually corrupt the last chunk to have trailing bits set
1218        let last_chunk = bv_dirty.chunks.back_mut().unwrap();
1219        last_chunk[3] |= 0xF0; // Set some high bits in the last byte
1220                               // Should return true since we had invalid trailing bits
1221        assert!(bv_dirty.clear_trailing_bits());
1222        // After clearing, should return false
1223        assert!(!bv_dirty.clear_trailing_bits());
1224        check_trailing_bits_zero(&bv_dirty);
1225    }
1226
1227    #[test]
1228    fn test_get_set() {
1229        let mut bv: BitMap<4> = BitMap::new();
1230
1231        // Test initial state
1232        assert_eq!(bv.len(), 0);
1233        assert!(bv.is_empty());
1234
1235        // Test push
1236        bv.push(true);
1237        bv.push(false);
1238        bv.push(true);
1239        assert_eq!(bv.len(), 3);
1240        assert!(!bv.is_empty());
1241
1242        // Test get
1243        assert!(bv.get(0));
1244        assert!(!bv.get(1));
1245        assert!(bv.get(2));
1246
1247        bv.set(1, true);
1248        assert!(bv.get(1));
1249        bv.set(2, false);
1250        assert!(!bv.get(2));
1251
1252        // Test flip
1253        bv.flip(0); // true -> false
1254        assert!(!bv.get(0));
1255        bv.flip(0); // false -> true
1256        assert!(bv.get(0));
1257    }
1258
1259    #[test]
1260    fn test_chunk_operations() {
1261        let mut bv: BitMap<4> = BitMap::new();
1262        let test_chunk = hex!("0xABCDEF12");
1263
1264        // Test push_chunk
1265        bv.push_chunk(&test_chunk);
1266        assert_eq!(bv.len(), 32); // 4 bytes * 8 bits
1267
1268        // Test get_chunk
1269        let chunk = bv.get_chunk(0);
1270        assert_eq!(chunk, &test_chunk);
1271
1272        // Test get_chunk_containing
1273        let chunk = bv.get_chunk_containing(0);
1274        assert_eq!(chunk, &test_chunk);
1275
1276        // Test last_chunk
1277        let (last_chunk, next_bit) = bv.last_chunk();
1278        assert_eq!(next_bit, BitMap::<4>::CHUNK_SIZE_BITS); // Should be at chunk boundary
1279        assert_eq!(last_chunk, &test_chunk); // The chunk we just pushed
1280    }
1281
1282    #[test]
1283    fn test_pop() {
1284        let mut bv: BitMap<3> = BitMap::new();
1285        bv.push(true);
1286        assert!(bv.pop());
1287        assert_eq!(bv.len(), 0);
1288
1289        bv.push(false);
1290        assert!(!bv.pop());
1291        assert_eq!(bv.len(), 0);
1292
1293        bv.push(true);
1294        bv.push(false);
1295        bv.push(true);
1296        assert!(bv.pop());
1297        assert_eq!(bv.len(), 2);
1298        assert!(!bv.pop());
1299        assert_eq!(bv.len(), 1);
1300        assert!(bv.pop());
1301        assert_eq!(bv.len(), 0);
1302
1303        for i in 0..100 {
1304            bv.push(i % 2 == 0);
1305        }
1306        assert_eq!(bv.len(), 100);
1307        for i in (0..100).rev() {
1308            assert_eq!(bv.pop(), i % 2 == 0);
1309        }
1310        assert_eq!(bv.len(), 0);
1311        assert!(bv.is_empty());
1312    }
1313
1314    #[test]
1315    fn test_truncate() {
1316        let mut bv: BitMap<4> = BitMap::new();
1317        let expected: Vec<bool> = (0..70).map(|i| i % 3 == 0).collect();
1318        for &bit in &expected {
1319            bv.push(bit);
1320        }
1321
1322        bv.truncate(65);
1323        assert_eq!(bv.len(), 65);
1324        for i in 0..65 {
1325            assert_eq!(bv.get(i), expected[i as usize]);
1326        }
1327
1328        bv.truncate(32);
1329        assert_eq!(bv.len(), 32);
1330        for i in 0..32 {
1331            assert_eq!(bv.get(i), expected[i as usize]);
1332        }
1333
1334        bv.truncate(0);
1335        assert_eq!(bv.len(), 0);
1336        assert!(bv.is_empty());
1337    }
1338
1339    #[test]
1340    #[should_panic(expected = "cannot truncate to a larger size")]
1341    fn test_truncate_larger_size_panics() {
1342        let mut bv: BitMap<4> = BitMap::new();
1343        bv.push(true);
1344        bv.truncate(2);
1345    }
1346
1347    #[test]
1348    fn test_pop_chunk() {
1349        let mut bv: BitMap<3> = BitMap::new();
1350        const CHUNK_SIZE: u64 = BitMap::<3>::CHUNK_SIZE_BITS;
1351
1352        // Test 1: Pop a single chunk and verify it returns the correct data
1353        let chunk1 = hex!("0xAABBCC");
1354        bv.push_chunk(&chunk1);
1355        assert_eq!(bv.len(), CHUNK_SIZE);
1356        let popped = bv.pop_chunk();
1357        assert_eq!(popped, chunk1);
1358        assert_eq!(bv.len(), 0);
1359        assert!(bv.is_empty());
1360
1361        // Test 2: Pop multiple chunks in reverse order
1362        let chunk2 = hex!("0x112233");
1363        let chunk3 = hex!("0x445566");
1364        let chunk4 = hex!("0x778899");
1365
1366        bv.push_chunk(&chunk2);
1367        bv.push_chunk(&chunk3);
1368        bv.push_chunk(&chunk4);
1369        assert_eq!(bv.len(), CHUNK_SIZE * 3);
1370
1371        assert_eq!(bv.pop_chunk(), chunk4);
1372        assert_eq!(bv.len(), CHUNK_SIZE * 2);
1373
1374        assert_eq!(bv.pop_chunk(), chunk3);
1375        assert_eq!(bv.len(), CHUNK_SIZE);
1376
1377        assert_eq!(bv.pop_chunk(), chunk2);
1378        assert_eq!(bv.len(), 0);
1379
1380        // Test 3: Verify data integrity when popping chunks
1381        let first_chunk = hex!("0xAABBCC");
1382        let second_chunk = hex!("0x112233");
1383        bv.push_chunk(&first_chunk);
1384        bv.push_chunk(&second_chunk);
1385
1386        // Pop the second chunk, verify it and that first chunk is intact
1387        assert_eq!(bv.pop_chunk(), second_chunk);
1388        assert_eq!(bv.len(), CHUNK_SIZE);
1389
1390        for i in 0..CHUNK_SIZE {
1391            let byte_idx = (i / 8) as usize;
1392            let bit_idx = i % 8;
1393            let expected = (first_chunk[byte_idx] >> bit_idx) & 1 == 1;
1394            assert_eq!(bv.get(i), expected);
1395        }
1396
1397        assert_eq!(bv.pop_chunk(), first_chunk);
1398        assert_eq!(bv.len(), 0);
1399    }
1400
1401    #[test]
1402    #[should_panic(expected = "cannot pop chunk when not chunk aligned")]
1403    fn test_pop_chunk_not_aligned() {
1404        let mut bv: BitMap<3> = BitMap::new();
1405
1406        // Push a full chunk plus one bit
1407        bv.push_chunk(&[0xFF; 3]);
1408        bv.push(true);
1409
1410        // Should panic because not chunk-aligned
1411        bv.pop_chunk();
1412    }
1413
1414    #[test]
1415    #[should_panic(expected = "cannot pop chunk: bitmap has fewer than CHUNK_SIZE_BITS bits")]
1416    fn test_pop_chunk_insufficient_bits() {
1417        let mut bv: BitMap<3> = BitMap::new();
1418
1419        // Push only a few bits (less than a full chunk)
1420        bv.push(true);
1421        bv.push(false);
1422
1423        // Should panic because we don't have a full chunk to pop
1424        bv.pop_chunk();
1425    }
1426
1427    #[test]
1428    fn test_byte_operations() {
1429        let mut bv: BitMap<4> = BitMap::new();
1430
1431        // Test push_byte
1432        bv.push_byte(0xFF);
1433        assert_eq!(bv.len(), 8);
1434
1435        // All bits in the byte should be set
1436        for i in 0..8 {
1437            assert!(bv.get(i as u64));
1438        }
1439
1440        bv.push_byte(0x00);
1441        assert_eq!(bv.len(), 16);
1442
1443        // All bits in the second byte should be clear
1444        for i in 8..16 {
1445            assert!(!bv.get(i as u64));
1446        }
1447    }
1448
1449    #[test]
1450    fn test_count_operations() {
1451        let mut bv: BitMap<4> = BitMap::new();
1452
1453        // Empty bitmap
1454        assert_eq!(bv.count_ones(), 0);
1455        assert_eq!(bv.count_zeros(), 0);
1456
1457        // Add some bits
1458        bv.push(true);
1459        bv.push(false);
1460        bv.push(true);
1461        bv.push(true);
1462        bv.push(false);
1463
1464        assert_eq!(bv.count_ones(), 3);
1465        assert_eq!(bv.count_zeros(), 2);
1466        assert_eq!(bv.len(), 5);
1467
1468        // Test with full bytes
1469        let mut bv2: BitMap<4> = BitMap::new();
1470        bv2.push_byte(0xFF); // 8 ones
1471        bv2.push_byte(0x00); // 8 zeros
1472        bv2.push_byte(0xAA); // 4 ones, 4 zeros (10101010)
1473
1474        assert_eq!(bv2.count_ones(), 12);
1475        assert_eq!(bv2.count_zeros(), 12);
1476        assert_eq!(bv2.len(), 24);
1477    }
1478
1479    #[test]
1480    fn test_set_all() {
1481        let mut bv: BitMap<1> = BitMap::new();
1482
1483        // Add some bits
1484        bv.push(true);
1485        bv.push(false);
1486        bv.push(true);
1487        bv.push(false);
1488        bv.push(true);
1489        bv.push(false);
1490        bv.push(true);
1491        bv.push(false);
1492        bv.push(true);
1493        bv.push(false);
1494
1495        assert_eq!(bv.len(), 10);
1496        assert_eq!(bv.count_ones(), 5);
1497        assert_eq!(bv.count_zeros(), 5);
1498
1499        // Test set_all(true)
1500        bv.set_all(true);
1501        assert_eq!(bv.len(), 10);
1502        assert_eq!(bv.count_ones(), 10);
1503        assert_eq!(bv.count_zeros(), 0);
1504
1505        // Test set_all(false)
1506        bv.set_all(false);
1507        assert_eq!(bv.len(), 10);
1508        assert_eq!(bv.count_ones(), 0);
1509        assert_eq!(bv.count_zeros(), 10);
1510    }
1511
1512    #[test]
1513    fn test_flip_all() {
1514        let mut bv: BitMap<4> = BitMap::new();
1515
1516        bv.push(true);
1517        bv.push(false);
1518        bv.push(true);
1519        bv.push(false);
1520        bv.push(true);
1521
1522        let original_ones = bv.count_ones();
1523        let original_zeros = bv.count_zeros();
1524        let original_len = bv.len();
1525
1526        bv.flip_all();
1527
1528        // Length should not change
1529        assert_eq!(bv.len(), original_len);
1530
1531        // Ones and zeros should be swapped
1532        assert_eq!(bv.count_ones(), original_zeros);
1533        assert_eq!(bv.count_zeros(), original_ones);
1534
1535        // Check bits
1536        assert!(!bv.get(0));
1537        assert!(bv.get(1));
1538        assert!(!bv.get(2));
1539        assert!(bv.get(3));
1540        assert!(!bv.get(4));
1541    }
1542
1543    #[test]
1544    fn test_bitwise_and() {
1545        let mut bv1: BitMap<4> = BitMap::new();
1546        let mut bv2: BitMap<4> = BitMap::new();
1547
1548        // Create test patterns: 10110 & 11010 = 10010
1549        let pattern1 = [true, false, true, true, false];
1550        let pattern2 = [true, true, false, true, false];
1551        let expected = [true, false, false, true, false];
1552
1553        for &bit in &pattern1 {
1554            bv1.push(bit);
1555        }
1556        for &bit in &pattern2 {
1557            bv2.push(bit);
1558        }
1559
1560        bv1.and(&bv2);
1561
1562        assert_eq!(bv1.len(), 5);
1563        for (i, &expected_bit) in expected.iter().enumerate() {
1564            assert_eq!(bv1.get(i as u64), expected_bit);
1565        }
1566    }
1567
1568    #[test]
1569    fn test_bitwise_or() {
1570        let mut bv1: BitMap<4> = BitMap::new();
1571        let mut bv2: BitMap<4> = BitMap::new();
1572
1573        // Create test patterns: 10110 | 11010 = 11110
1574        let pattern1 = [true, false, true, true, false];
1575        let pattern2 = [true, true, false, true, false];
1576        let expected = [true, true, true, true, false];
1577
1578        for &bit in &pattern1 {
1579            bv1.push(bit);
1580        }
1581        for &bit in &pattern2 {
1582            bv2.push(bit);
1583        }
1584
1585        bv1.or(&bv2);
1586
1587        assert_eq!(bv1.len(), 5);
1588        for (i, &expected_bit) in expected.iter().enumerate() {
1589            assert_eq!(bv1.get(i as u64), expected_bit);
1590        }
1591    }
1592
1593    #[test]
1594    fn test_bitwise_xor() {
1595        let mut bv1: BitMap<4> = BitMap::new();
1596        let mut bv2: BitMap<4> = BitMap::new();
1597
1598        // Create test patterns: 10110 ^ 11010 = 01100
1599        let pattern1 = [true, false, true, true, false];
1600        let pattern2 = [true, true, false, true, false];
1601        let expected = [false, true, true, false, false];
1602
1603        for &bit in &pattern1 {
1604            bv1.push(bit);
1605        }
1606        for &bit in &pattern2 {
1607            bv2.push(bit);
1608        }
1609
1610        bv1.xor(&bv2);
1611
1612        assert_eq!(bv1.len(), 5);
1613        for (i, &expected_bit) in expected.iter().enumerate() {
1614            assert_eq!(bv1.get(i as u64), expected_bit);
1615        }
1616    }
1617
1618    #[test]
1619    fn test_multi_chunk_operations() {
1620        let mut bv1: BitMap<4> = BitMap::new();
1621        let mut bv2: BitMap<4> = BitMap::new();
1622
1623        // Fill multiple chunks
1624        let chunk1 = hex!("0xAABBCCDD"); // 10101010 10111011 11001100 11011101
1625        let chunk2 = hex!("0x55667788"); // 01010101 01100110 01110111 10001000
1626
1627        bv1.push_chunk(&chunk1);
1628        bv1.push_chunk(&chunk1);
1629        bv2.push_chunk(&chunk2);
1630        bv2.push_chunk(&chunk2);
1631
1632        assert_eq!(bv1.len(), 64);
1633        assert_eq!(bv2.len(), 64);
1634
1635        // Test AND operation
1636        let mut bv_and = bv1.clone();
1637        bv_and.and(&bv2);
1638
1639        // Test OR operation
1640        let mut bv_or = bv1.clone();
1641        bv_or.or(&bv2);
1642
1643        // Test XOR operation
1644        let mut bv_xor = bv1.clone();
1645        bv_xor.xor(&bv2);
1646
1647        // Verify results make sense
1648        assert_eq!(bv_and.len(), 64);
1649        assert_eq!(bv_or.len(), 64);
1650        assert_eq!(bv_xor.len(), 64);
1651
1652        // AND should have fewer or equal ones than either operand
1653        assert!(bv_and.count_ones() <= bv1.count_ones());
1654        assert!(bv_and.count_ones() <= bv2.count_ones());
1655
1656        // OR should have more or equal ones than either operand
1657        assert!(bv_or.count_ones() >= bv1.count_ones());
1658        assert!(bv_or.count_ones() >= bv2.count_ones());
1659    }
1660
1661    #[test]
1662    fn test_partial_chunk_operations() {
1663        let mut bv1: BitMap<4> = BitMap::new();
1664        let mut bv2: BitMap<4> = BitMap::new();
1665
1666        // Add partial chunks (not aligned to chunk boundaries)
1667        for i in 0..35 {
1668            // 35 bits = 4 bytes + 3 bits
1669            bv1.push(i % 2 == 0);
1670            bv2.push(i % 3 == 0);
1671        }
1672
1673        assert_eq!(bv1.len(), 35);
1674        assert_eq!(bv2.len(), 35);
1675
1676        // Test operations with partial chunks
1677        let mut bv_and = bv1.clone();
1678        bv_and.and(&bv2);
1679
1680        let mut bv_or = bv1.clone();
1681        bv_or.or(&bv2);
1682
1683        let mut bv_xor = bv1.clone();
1684        bv_xor.xor(&bv2);
1685
1686        // All should maintain the same length
1687        assert_eq!(bv_and.len(), 35);
1688        assert_eq!(bv_or.len(), 35);
1689        assert_eq!(bv_xor.len(), 35);
1690
1691        // Test flip_all with partial chunk
1692        let mut bv_inv = bv1.clone();
1693        let original_ones = bv_inv.count_ones();
1694        let original_zeros = bv_inv.count_zeros();
1695        bv_inv.flip_all();
1696        assert_eq!(bv_inv.count_ones(), original_zeros);
1697        assert_eq!(bv_inv.count_zeros(), original_ones);
1698    }
1699
1700    #[test]
1701    #[should_panic(expected = "bit 1 out of bounds (len: 1)")]
1702    fn test_flip_out_of_bounds() {
1703        let mut bv: BitMap<4> = BitMap::new();
1704        bv.push(true);
1705        bv.flip(1); // Only bit 0 exists
1706    }
1707
1708    #[test]
1709    #[should_panic(expected = "BitMap lengths don't match: 2 vs 1")]
1710    fn test_and_length_mismatch() {
1711        let mut bv1: BitMap<4> = BitMap::new();
1712        let mut bv2: BitMap<4> = BitMap::new();
1713
1714        bv1.push(true);
1715        bv1.push(false);
1716        bv2.push(true); // Different length
1717
1718        bv1.and(&bv2);
1719    }
1720
1721    #[test]
1722    #[should_panic(expected = "BitMap lengths don't match: 1 vs 2")]
1723    fn test_or_length_mismatch() {
1724        let mut bv1: BitMap<4> = BitMap::new();
1725        let mut bv2: BitMap<4> = BitMap::new();
1726
1727        bv1.push(true);
1728        bv2.push(true);
1729        bv2.push(false); // Different length
1730
1731        bv1.or(&bv2);
1732    }
1733
1734    #[test]
1735    #[should_panic(expected = "BitMap lengths don't match: 3 vs 2")]
1736    fn test_xor_length_mismatch() {
1737        let mut bv1: BitMap<4> = BitMap::new();
1738        let mut bv2: BitMap<4> = BitMap::new();
1739
1740        bv1.push(true);
1741        bv1.push(false);
1742        bv1.push(true);
1743        bv2.push(true);
1744        bv2.push(false); // Different length
1745
1746        bv1.xor(&bv2);
1747    }
1748
1749    #[test]
1750    fn test_equality() {
1751        // Test empty bitmaps
1752        assert_eq!(BitMap::<4>::new(), BitMap::<4>::new());
1753        assert_eq!(BitMap::<8>::new(), BitMap::<8>::new());
1754
1755        // Test non-empty bitmaps from constructors
1756        let pattern = [true, false, true, true, false, false, true, false, true];
1757        let bv4: BitMap<4> = pattern.as_ref().into();
1758        assert_eq!(bv4, BitMap::<4>::from(pattern.as_ref()));
1759        let bv8: BitMap<8> = pattern.as_ref().into();
1760        assert_eq!(bv8, BitMap::<8>::from(pattern.as_ref()));
1761
1762        // Test non-empty bitmaps from push operations
1763        let mut bv1: BitMap<4> = BitMap::new();
1764        let mut bv2: BitMap<4> = BitMap::new();
1765        for i in 0..33 {
1766            let bit = i % 3 == 0;
1767            bv1.push(bit);
1768            bv2.push(bit);
1769        }
1770        assert_eq!(bv1, bv2);
1771
1772        // Test inequality: different lengths
1773        bv1.push(true);
1774        assert_ne!(bv1, bv2);
1775        bv1.pop(); // Restore equality
1776        assert_eq!(bv1, bv2);
1777
1778        // Test inequality: different content
1779        bv1.flip(15);
1780        assert_ne!(bv1, bv2);
1781        bv1.flip(15); // Restore equality
1782        assert_eq!(bv1, bv2);
1783
1784        // Test equality after operations
1785        let mut bv_ops1 = BitMap::<16>::ones(25);
1786        let mut bv_ops2 = BitMap::<16>::ones(25);
1787        bv_ops1.flip_all();
1788        bv_ops2.flip_all();
1789        assert_eq!(bv_ops1, bv_ops2);
1790
1791        let mask_bits: Vec<bool> = (0..33).map(|i| i % 3 == 0).collect();
1792        let mask = BitMap::<4>::from(mask_bits);
1793        bv1.and(&mask);
1794        bv2.and(&mask);
1795        assert_eq!(bv1, bv2);
1796    }
1797
1798    #[test]
1799    fn test_different_chunk_sizes() {
1800        // Test with different chunk sizes
1801        let mut bv8: BitMap<8> = BitMap::new();
1802        let mut bv16: BitMap<16> = BitMap::new();
1803        let mut bv32: BitMap<32> = BitMap::new();
1804
1805        // Test chunk operations first (must be chunk-aligned)
1806        let chunk8 = [0xFF; 8];
1807        let chunk16 = [0xAA; 16];
1808        let chunk32 = [0x55; 32];
1809
1810        bv8.push_chunk(&chunk8);
1811        bv16.push_chunk(&chunk16);
1812        bv32.push_chunk(&chunk32);
1813
1814        // Test basic operations work with different sizes
1815        bv8.push(true);
1816        bv8.push(false);
1817        assert_eq!(bv8.len(), 64 + 2);
1818        assert_eq!(bv8.count_ones(), 64 + 1); // chunk8 is all 0xFF + 1 true bit
1819        assert_eq!(bv8.count_zeros(), 1);
1820
1821        bv16.push(true);
1822        bv16.push(false);
1823        assert_eq!(bv16.len(), 128 + 2);
1824        assert_eq!(bv16.count_ones(), 64 + 1); // chunk16 is 0xAA pattern + 1 true bit
1825        assert_eq!(bv16.count_zeros(), 64 + 1);
1826
1827        bv32.push(true);
1828        bv32.push(false);
1829        assert_eq!(bv32.len(), 256 + 2);
1830        assert_eq!(bv32.count_ones(), 128 + 1); // chunk32 is 0x55 pattern + 1 true bit
1831        assert_eq!(bv32.count_zeros(), 128 + 1);
1832    }
1833
1834    #[test]
1835    fn test_iterator() {
1836        // Test empty iterator
1837        let bv: BitMap<4> = BitMap::new();
1838        let mut iter = bv.iter();
1839        assert_eq!(iter.next(), None);
1840        assert_eq!(iter.size_hint(), (0, Some(0)));
1841
1842        // Test iterator with some bits
1843        let pattern = [true, false, true, false, true];
1844        let bv: BitMap<4> = pattern.as_ref().into();
1845
1846        // Collect all bits via iterator
1847        let collected: Vec<bool> = bv.iter().collect();
1848        assert_eq!(collected, pattern);
1849
1850        // Test size_hint
1851        let mut iter = bv.iter();
1852        assert_eq!(iter.size_hint(), (5, Some(5)));
1853
1854        // Consume one element and check size_hint again
1855        assert_eq!(iter.next(), Some(true));
1856        assert_eq!(iter.size_hint(), (4, Some(4)));
1857
1858        // Test ExactSizeIterator
1859        let iter = bv.iter();
1860        assert_eq!(iter.len(), 5);
1861
1862        // Test iterator with larger bitmap
1863        let mut large_bv: BitMap<8> = BitMap::new();
1864        for i in 0..100 {
1865            large_bv.push(i % 3 == 0);
1866        }
1867
1868        let collected: Vec<bool> = large_bv.iter().collect();
1869        assert_eq!(collected.len(), 100);
1870        for (i, &bit) in collected.iter().enumerate() {
1871            assert_eq!(bit, i % 3 == 0);
1872        }
1873    }
1874
1875    #[test]
1876    fn test_iterator_edge_cases() {
1877        // Test iterator with single bit
1878        let mut bv: BitMap<4> = BitMap::new();
1879        bv.push(true);
1880
1881        let collected: Vec<bool> = bv.iter().collect();
1882        assert_eq!(collected, vec![true]);
1883
1884        // Test iterator across chunk boundaries
1885        let mut bv: BitMap<4> = BitMap::new();
1886        // Fill exactly one chunk (32 bits)
1887        for i in 0..32 {
1888            bv.push(i % 2 == 0);
1889        }
1890        // Add a few more bits in the next chunk
1891        bv.push(true);
1892        bv.push(false);
1893        bv.push(true);
1894
1895        let collected: Vec<bool> = bv.iter().collect();
1896        assert_eq!(collected.len(), 35);
1897
1898        // Verify the pattern
1899        for (i, &bit) in collected.iter().enumerate().take(32) {
1900            assert_eq!(bit, i % 2 == 0);
1901        }
1902        assert!(collected[32]);
1903        assert!(!collected[33]);
1904        assert!(collected[34]);
1905    }
1906
1907    #[test]
1908    fn test_ones_iter_empty() {
1909        let bv: BitMap<4> = BitMap::new();
1910        let ones: Vec<u64> = bv.ones_iter().collect();
1911        assert!(ones.is_empty());
1912    }
1913
1914    #[test]
1915    fn test_ones_iter_all_zeros() {
1916        let bv = BitMap::<4>::zeroes(100);
1917        let ones: Vec<u64> = bv.ones_iter().collect();
1918        assert!(ones.is_empty());
1919    }
1920
1921    #[test]
1922    fn test_ones_iter_all_ones() {
1923        let bv = BitMap::<4>::ones(100);
1924        let ones: Vec<u64> = bv.ones_iter().collect();
1925        let expected: Vec<u64> = (0..100).collect();
1926        assert_eq!(ones, expected);
1927    }
1928
1929    #[test]
1930    fn test_ones_iter_sparse() {
1931        let mut bv = BitMap::<4>::zeroes(64);
1932        bv.set(0, true);
1933        bv.set(31, true);
1934        bv.set(32, true);
1935        bv.set(63, true);
1936
1937        let ones: Vec<u64> = bv.ones_iter().collect();
1938        assert_eq!(ones, vec![0, 31, 32, 63]);
1939    }
1940
1941    #[test]
1942    fn test_ones_iter_single_bit() {
1943        let mut bv: BitMap<4> = BitMap::new();
1944        bv.push(true);
1945        assert_eq!(bv.ones_iter().collect::<Vec<_>>(), vec![0]);
1946
1947        let mut bv: BitMap<4> = BitMap::new();
1948        bv.push(false);
1949        assert!(bv.ones_iter().collect::<Vec<_>>().is_empty());
1950    }
1951
1952    #[test]
1953    fn test_ones_iter_multi_chunk() {
1954        // Use small chunks (4 bytes = 32 bits) to ensure multi-chunk coverage.
1955        let mut bv = BitMap::<4>::zeroes(96);
1956        // Set one bit per chunk.
1957        bv.set(7, true); // chunk 0
1958        bv.set(40, true); // chunk 1
1959        bv.set(95, true); // chunk 2
1960
1961        let ones: Vec<u64> = bv.ones_iter().collect();
1962        assert_eq!(ones, vec![7, 40, 95]);
1963    }
1964
1965    #[test]
1966    fn test_ones_iter_partial_chunk() {
1967        // 35 bits = 1 full chunk (32 bits) + 3 bits in a partial chunk.
1968        let mut bv = BitMap::<4>::zeroes(35);
1969        bv.set(31, true); // last bit of full chunk
1970        bv.set(32, true); // first bit of partial chunk
1971        bv.set(34, true); // last bit
1972
1973        let ones: Vec<u64> = bv.ones_iter().collect();
1974        assert_eq!(ones, vec![31, 32, 34]);
1975    }
1976
1977    #[test]
1978    fn test_ones_iter_from_midway() {
1979        let mut bv = BitMap::<4>::zeroes(64);
1980        bv.set(5, true);
1981        bv.set(20, true);
1982        bv.set(40, true);
1983        bv.set(60, true);
1984
1985        // Start from position 20 -- should skip bit 5.
1986        let ones: Vec<u64> = Readable::ones_iter_from(&bv, 20).collect();
1987        assert_eq!(ones, vec![20, 40, 60]);
1988
1989        // Start from position 21 -- should skip bits 5 and 20.
1990        let ones: Vec<u64> = Readable::ones_iter_from(&bv, 21).collect();
1991        assert_eq!(ones, vec![40, 60]);
1992
1993        // Start past all set bits.
1994        let ones: Vec<u64> = Readable::ones_iter_from(&bv, 61).collect();
1995        assert!(ones.is_empty());
1996    }
1997
1998    #[test]
1999    fn test_ones_iter_matches_count_ones() {
2000        let mut bv: BitMap<8> = BitMap::new();
2001        for i in 0..200 {
2002            bv.push(i % 7 == 0);
2003        }
2004        assert_eq!(bv.ones_iter().count() as u64, bv.count_ones());
2005    }
2006
2007    #[test]
2008    fn test_ones_iter_different_chunk_sizes() {
2009        let pattern: Vec<bool> = (0..100).map(|i| i % 5 == 0).collect();
2010        let expected: Vec<u64> = (0..100).filter(|i| i % 5 == 0).collect();
2011
2012        let bv4: BitMap<4> = pattern.as_slice().into();
2013        let bv8: BitMap<8> = pattern.as_slice().into();
2014        let bv16: BitMap<16> = pattern.as_slice().into();
2015
2016        assert_eq!(bv4.ones_iter().collect::<Vec<_>>(), expected);
2017        assert_eq!(bv8.ones_iter().collect::<Vec<_>>(), expected);
2018        assert_eq!(bv16.ones_iter().collect::<Vec<_>>(), expected);
2019    }
2020
2021    #[test]
2022    fn test_codec_roundtrip() {
2023        // Test empty bitmap
2024        let original: BitMap<4> = BitMap::new();
2025        let encoded = original.encode();
2026        let decoded = BitMap::decode_cfg(&mut encoded.as_ref(), &(usize::MAX as u64)).unwrap();
2027        assert_eq!(original, decoded);
2028
2029        // Test small bitmap
2030        let pattern = [true, false, true, false, true];
2031        let original: BitMap<4> = pattern.as_ref().into();
2032        let encoded = original.encode();
2033        let decoded = BitMap::decode_cfg(&mut encoded.as_ref(), &(usize::MAX as u64)).unwrap();
2034        assert_eq!(original, decoded);
2035
2036        // Verify the decoded bitmap has the same bits
2037        for (i, &expected) in pattern.iter().enumerate() {
2038            assert_eq!(decoded.get(i as u64), expected);
2039        }
2040
2041        // Test larger bitmap across multiple chunks
2042        let mut large_original: BitMap<8> = BitMap::new();
2043        for i in 0..100 {
2044            large_original.push(i % 7 == 0);
2045        }
2046
2047        let encoded = large_original.encode();
2048        let decoded = BitMap::decode_cfg(&mut encoded.as_ref(), &(usize::MAX as u64)).unwrap();
2049        assert_eq!(large_original, decoded);
2050
2051        // Verify all bits match
2052        assert_eq!(decoded.len(), 100);
2053        for i in 0..100 {
2054            assert_eq!(decoded.get(i as u64), i % 7 == 0);
2055        }
2056    }
2057
2058    #[test]
2059    fn test_codec_different_chunk_sizes() {
2060        let pattern = [true, false, true, true, false, false, true];
2061
2062        // Test with different chunk sizes
2063        let bv4: BitMap<4> = pattern.as_ref().into();
2064        let bv8: BitMap<8> = pattern.as_ref().into();
2065        let bv16: BitMap<16> = pattern.as_ref().into();
2066
2067        // Encode and decode each
2068        let encoded4 = bv4.encode();
2069        let decoded4 = BitMap::decode_cfg(&mut encoded4.as_ref(), &(usize::MAX as u64)).unwrap();
2070        assert_eq!(bv4, decoded4);
2071
2072        let encoded8 = bv8.encode();
2073        let decoded8 = BitMap::decode_cfg(&mut encoded8.as_ref(), &(usize::MAX as u64)).unwrap();
2074        assert_eq!(bv8, decoded8);
2075
2076        let encoded16 = bv16.encode();
2077        let decoded16 = BitMap::decode_cfg(&mut encoded16.as_ref(), &(usize::MAX as u64)).unwrap();
2078        assert_eq!(bv16, decoded16);
2079
2080        // All should have the same logical content
2081        for (i, &expected) in pattern.iter().enumerate() {
2082            let i = i as u64;
2083            assert_eq!(decoded4.get(i), expected);
2084            assert_eq!(decoded8.get(i), expected);
2085            assert_eq!(decoded16.get(i), expected);
2086        }
2087    }
2088
2089    #[test]
2090    fn test_codec_edge_cases() {
2091        // Test bitmap with exactly one chunk filled
2092        let mut bv: BitMap<4> = BitMap::new();
2093        for i in 0..32 {
2094            bv.push(i % 2 == 0);
2095        }
2096
2097        let encoded = bv.encode();
2098        let decoded = BitMap::decode_cfg(&mut encoded.as_ref(), &(usize::MAX as u64)).unwrap();
2099        assert_eq!(bv, decoded);
2100        assert_eq!(decoded.len(), 32);
2101
2102        // Test bitmap with partial chunk
2103        let mut bv2: BitMap<4> = BitMap::new();
2104        for i in 0..35 {
2105            // 32 + 3 bits
2106            bv2.push(i % 3 == 0);
2107        }
2108
2109        let encoded2 = bv2.encode();
2110        let decoded2 = BitMap::decode_cfg(&mut encoded2.as_ref(), &(usize::MAX as u64)).unwrap();
2111        assert_eq!(bv2, decoded2);
2112        assert_eq!(decoded2.len(), 35);
2113    }
2114
2115    #[test]
2116    fn test_encode_size() {
2117        // Test encode size calculation
2118        let bv: BitMap<4> = BitMap::new();
2119        let encoded = bv.encode();
2120        assert_eq!(bv.encode_size(), encoded.len());
2121
2122        // Test with some data
2123        let pattern = [true, false, true, false, true];
2124        let bv: BitMap<4> = pattern.as_ref().into();
2125        let encoded = bv.encode();
2126        assert_eq!(bv.encode_size(), encoded.len());
2127
2128        // Test with larger data
2129        let mut large_bv: BitMap<8> = BitMap::new();
2130        for i in 0..100 {
2131            large_bv.push(i % 2 == 0);
2132        }
2133        let encoded = large_bv.encode();
2134        assert_eq!(large_bv.encode_size(), encoded.len());
2135    }
2136
2137    #[test]
2138    fn test_codec_empty_chunk_optimization() {
2139        // Test that empty last chunks are not serialized
2140
2141        // Case 1: Empty bitmap (omits the only empty chunk)
2142        let bv_empty: BitMap<4> = BitMap::new();
2143        let encoded_empty = bv_empty.encode();
2144        let decoded_empty: BitMap<4> =
2145            BitMap::decode_cfg(&mut encoded_empty.as_ref(), &(usize::MAX as u64)).unwrap();
2146        assert_eq!(bv_empty, decoded_empty);
2147        assert_eq!(bv_empty.len(), decoded_empty.len());
2148        // Should only encode the length, no chunks
2149        assert_eq!(encoded_empty.len(), bv_empty.len().encode_size());
2150
2151        // Case 2: Bitmap ending exactly at chunk boundary (omits empty last chunk)
2152        let mut bv_exact: BitMap<4> = BitMap::new();
2153        for _ in 0..32 {
2154            bv_exact.push(true);
2155        }
2156        let encoded_exact = bv_exact.encode();
2157        let decoded_exact: BitMap<4> =
2158            BitMap::decode_cfg(&mut encoded_exact.as_ref(), &(usize::MAX as u64)).unwrap();
2159        assert_eq!(bv_exact, decoded_exact);
2160
2161        // Case 3: Bitmap with partial last chunk (includes last chunk)
2162        let mut bv_partial: BitMap<4> = BitMap::new();
2163        for _ in 0..35 {
2164            bv_partial.push(true);
2165        }
2166        let encoded_partial = bv_partial.encode();
2167        let decoded_partial: BitMap<4> =
2168            BitMap::decode_cfg(&mut encoded_partial.as_ref(), &(usize::MAX as u64)).unwrap();
2169        assert_eq!(bv_partial, decoded_partial);
2170        assert_eq!(bv_partial.len(), decoded_partial.len());
2171
2172        // Verify optimization works correctly
2173        assert!(encoded_exact.len() < encoded_partial.len());
2174        assert_eq!(encoded_exact.len(), bv_exact.len().encode_size() + 4); // length + 1 chunk
2175        assert_eq!(encoded_partial.len(), bv_partial.len().encode_size() + 8); // length + 2 chunks
2176    }
2177
2178    #[test]
2179    fn test_codec_error_cases() {
2180        // Test invalid length with range check
2181        let mut buf = BytesMut::new();
2182        100u64.write(&mut buf); // bits length
2183
2184        // 100 bits requires 4 chunks (3 full + partially filled)
2185        for _ in 0..4 {
2186            [0u8; 4].write(&mut buf);
2187        }
2188
2189        // Test with a restricted range that excludes 100
2190        let result = BitMap::<4>::decode_cfg(&mut buf, &99);
2191        assert!(matches!(result, Err(CodecError::InvalidLength(100))));
2192
2193        // Test truncated buffer (not enough chunks)
2194        let mut buf = BytesMut::new();
2195        100u64.write(&mut buf); // bits length requiring 4 chunks (3 full + partially filled)
2196                                // Only write 3 chunks
2197        [0u8; 4].write(&mut buf);
2198        [0u8; 4].write(&mut buf);
2199        [0u8; 4].write(&mut buf);
2200
2201        let result = BitMap::<4>::decode_cfg(&mut buf, &(usize::MAX as u64));
2202        // Should fail when trying to read missing chunks
2203        assert!(result.is_err());
2204
2205        // Test invalid trailing bits
2206
2207        // Create a valid bitmap and encode it
2208        let original: BitMap<4> = BitMap::ones(20);
2209        let mut buf = BytesMut::new();
2210        original.write(&mut buf);
2211
2212        // Manually corrupt the encoded data by setting trailing bits
2213        let corrupted_data = buf.freeze();
2214        let mut corrupted_bytes = corrupted_data.to_vec();
2215
2216        // The last byte should have some trailing bits set to 1
2217        // For 20 bits with 4-byte chunks: 20 bits = 2.5 bytes, so last byte should have 4 valid bits
2218        // Set the high 4 bits of the last byte to 1 (these should be 0)
2219        let last_byte_idx = corrupted_bytes.len() - 1;
2220        corrupted_bytes[last_byte_idx] |= 0xF0;
2221
2222        // Read should fail
2223        let result = BitMap::<4>::read_cfg(&mut corrupted_bytes.as_slice(), &(usize::MAX as u64));
2224        assert!(matches!(
2225            result,
2226            Err(CodecError::Invalid(
2227                "BitMap",
2228                "Invalid trailing bits in encoded data"
2229            ))
2230        ));
2231    }
2232
2233    #[test]
2234    fn test_codec_range_config() {
2235        // Test RangeCfg validation in read_cfg
2236
2237        // Create a bitmap with 100 bits
2238        let mut original: BitMap<4> = BitMap::new();
2239        for i in 0..100 {
2240            original.push(i % 3 == 0);
2241        }
2242
2243        // Write to a buffer
2244        let mut buf = BytesMut::new();
2245        original.write(&mut buf);
2246
2247        // Test with max length < actual size (should fail)
2248        let result = BitMap::<4>::decode_cfg(&mut buf.as_ref(), &50);
2249        assert!(matches!(result, Err(CodecError::InvalidLength(100))));
2250
2251        // Test with max length == actual size (should succeed)
2252        let decoded = BitMap::<4>::decode_cfg(&mut buf.as_ref(), &100).unwrap();
2253        assert_eq!(decoded.len(), 100);
2254        assert_eq!(decoded, original);
2255
2256        // Test with max length > actual size (should succeed)
2257        let decoded = BitMap::<4>::decode_cfg(&mut buf.as_ref(), &101).unwrap();
2258        assert_eq!(decoded.len(), 100);
2259        assert_eq!(decoded, original);
2260
2261        // Test empty bitmap
2262        let empty = BitMap::<4>::new();
2263        let mut buf = BytesMut::new();
2264        empty.write(&mut buf);
2265
2266        // Empty bitmap should work with max length 0
2267        let decoded = BitMap::<4>::decode_cfg(&mut buf.as_ref(), &0).unwrap();
2268        assert_eq!(decoded.len(), 0);
2269        assert!(decoded.is_empty());
2270
2271        // Empty bitmap should work with max length > 0
2272        let decoded = BitMap::<4>::decode_cfg(&mut buf.as_ref(), &1).unwrap();
2273        assert_eq!(decoded.len(), 0);
2274        assert!(decoded.is_empty());
2275    }
2276
2277    #[test]
2278    fn test_from() {
2279        // Test From trait with different input types
2280
2281        // Test with Vec<bool>
2282        let vec_bool = vec![true, false, true, false, true];
2283        let bv: BitMap<4> = vec_bool.into();
2284        assert_eq!(bv.len(), 5);
2285        assert_eq!(bv.count_ones(), 3);
2286        assert_eq!(bv.count_zeros(), 2);
2287        for (i, &expected) in [true, false, true, false, true].iter().enumerate() {
2288            assert_eq!(bv.get(i as u64), expected);
2289        }
2290
2291        // Test with array slice
2292        let array = [false, true, true, false];
2293        let bv: BitMap<4> = (&array).into();
2294        assert_eq!(bv.len(), 4);
2295        assert_eq!(bv.count_ones(), 2);
2296        assert_eq!(bv.count_zeros(), 2);
2297        for (i, &expected) in array.iter().enumerate() {
2298            assert_eq!(bv.get(i as u64), expected);
2299        }
2300
2301        // Test with empty slice
2302        let empty: Vec<bool> = vec![];
2303        let bv: BitMap<4> = empty.into();
2304        assert_eq!(bv.len(), 0);
2305        assert!(bv.is_empty());
2306
2307        // Test with large slice
2308        let large: Vec<bool> = (0..100).map(|i| i % 3 == 0).collect();
2309        let bv: BitMap<8> = large.clone().into();
2310        assert_eq!(bv.len(), 100);
2311        for (i, &expected) in large.iter().enumerate() {
2312            assert_eq!(bv.get(i as u64), expected);
2313        }
2314    }
2315
2316    #[test]
2317    fn test_debug_formatting() {
2318        // Test Debug formatting for different sizes
2319
2320        // Test empty bitmap
2321        let bv: BitMap<4> = BitMap::new();
2322        let debug_str = format!("{bv:?}");
2323        assert_eq!(debug_str, "BitMap[]");
2324
2325        // Test small bitmap (should show all bits)
2326        let bv: BitMap<4> = [true, false, true, false, true].as_ref().into();
2327        let debug_str = format!("{bv:?}");
2328        assert_eq!(debug_str, "BitMap[10101]");
2329
2330        // Test bitmap at the display limit (64 bits)
2331        let pattern: Vec<bool> = (0..64).map(|i| i % 2 == 0).collect();
2332        let bv: BitMap<8> = pattern.into();
2333        let debug_str = format!("{bv:?}");
2334        let expected_pattern = "1010".repeat(16); // 64 bits alternating
2335        assert_eq!(debug_str, format!("BitMap[{expected_pattern}]"));
2336
2337        // Test large bitmap (should show ellipsis)
2338        let large_pattern: Vec<bool> = (0..100).map(|i| i % 2 == 0).collect();
2339        let bv: BitMap<16> = large_pattern.into();
2340        let debug_str = format!("{bv:?}");
2341
2342        // Should show first 32 bits + "..." + last 32 bits
2343        let first_32 = "10".repeat(16); // First 32 bits: 1010...
2344        let last_32 = "10".repeat(16); // Last 32 bits: ...1010
2345        let expected = format!("BitMap[{first_32}...{last_32}]");
2346        assert_eq!(debug_str, expected);
2347
2348        // Test single bit
2349        let bv: BitMap<4> = [true].as_ref().into();
2350        assert_eq!(format!("{bv:?}"), "BitMap[1]");
2351
2352        let bv: BitMap<4> = [false].as_ref().into();
2353        assert_eq!(format!("{bv:?}"), "BitMap[0]");
2354
2355        // Test exactly at boundary (65 bits - should show ellipsis)
2356        let pattern: Vec<bool> = (0..65).map(|i| i == 0 || i == 64).collect(); // First and last bits are true
2357        let bv: BitMap<16> = pattern.into();
2358        let debug_str = format!("{bv:?}");
2359
2360        // Should show first 32 bits (100000...) + "..." + last 32 bits (...000001)
2361        let first_32 = "1".to_string() + &"0".repeat(31);
2362        let last_32 = "0".repeat(31) + "1";
2363        let expected = format!("BitMap[{first_32}...{last_32}]");
2364        assert_eq!(debug_str, expected);
2365    }
2366
2367    #[test]
2368    fn test_from_different_chunk_sizes() {
2369        // Test From trait works with different chunk sizes
2370        let pattern = [true, false, true, true, false, false, true];
2371
2372        let bv4: BitMap<4> = pattern.as_ref().into();
2373        let bv8: BitMap<8> = pattern.as_ref().into();
2374        let bv16: BitMap<16> = pattern.as_ref().into();
2375
2376        // All should have the same content regardless of chunk size
2377        // Test each bitmap separately since they have different types
2378        for bv in [&bv4] {
2379            assert_eq!(bv.len(), 7);
2380            assert_eq!(bv.count_ones(), 4);
2381            assert_eq!(bv.count_zeros(), 3);
2382            for (i, &expected) in pattern.iter().enumerate() {
2383                assert_eq!(bv.get(i as u64), expected);
2384            }
2385        }
2386
2387        assert_eq!(bv8.len(), 7);
2388        assert_eq!(bv8.count_ones(), 4);
2389        assert_eq!(bv8.count_zeros(), 3);
2390        for (i, &expected) in pattern.iter().enumerate() {
2391            assert_eq!(bv8.get(i as u64), expected);
2392        }
2393
2394        assert_eq!(bv16.len(), 7);
2395        assert_eq!(bv16.count_ones(), 4);
2396        assert_eq!(bv16.count_zeros(), 3);
2397        for (i, &expected) in pattern.iter().enumerate() {
2398            assert_eq!(bv16.get(i as u64), expected);
2399        }
2400    }
2401
2402    #[test]
2403    fn test_prune_chunks() {
2404        let mut bv: BitMap<4> = BitMap::new();
2405        bv.push_chunk(&[1, 2, 3, 4]);
2406        bv.push_chunk(&[5, 6, 7, 8]);
2407        bv.push_chunk(&[9, 10, 11, 12]);
2408
2409        assert_eq!(bv.len(), 96);
2410        assert_eq!(bv.get_chunk(0), &[1, 2, 3, 4]);
2411
2412        // Prune first chunk
2413        bv.prune_chunks(1);
2414        assert_eq!(bv.len(), 64);
2415        assert_eq!(bv.get_chunk(0), &[5, 6, 7, 8]);
2416        assert_eq!(bv.get_chunk(1), &[9, 10, 11, 12]);
2417
2418        // Prune another chunk
2419        bv.prune_chunks(1);
2420        assert_eq!(bv.len(), 32);
2421        assert_eq!(bv.get_chunk(0), &[9, 10, 11, 12]);
2422    }
2423
2424    #[test]
2425    #[should_panic(expected = "cannot prune")]
2426    fn test_prune_too_many_chunks() {
2427        let mut bv: BitMap<4> = BitMap::new();
2428        bv.push_chunk(&[1, 2, 3, 4]);
2429        bv.push_chunk(&[5, 6, 7, 8]);
2430        bv.push(true);
2431
2432        // Try to prune 4 chunks when only 3 are available
2433        bv.prune_chunks(4);
2434    }
2435
2436    #[test]
2437    fn test_prune_with_partial_last_chunk() {
2438        let mut bv: BitMap<4> = BitMap::new();
2439        bv.push_chunk(&[1, 2, 3, 4]);
2440        bv.push_chunk(&[5, 6, 7, 8]);
2441        bv.push(true);
2442        bv.push(false);
2443
2444        assert_eq!(bv.len(), 66);
2445
2446        // Can prune first chunk
2447        bv.prune_chunks(1);
2448        assert_eq!(bv.len(), 34);
2449        assert_eq!(bv.get_chunk(0), &[5, 6, 7, 8]);
2450
2451        // Last partial chunk still has the appended bits
2452        assert!(bv.get(32));
2453        assert!(!bv.get(33));
2454    }
2455
2456    #[test]
2457    fn test_prune_all_chunks_resets_next_bit() {
2458        let mut bv: BitMap<4> = BitMap::new();
2459        bv.push_chunk(&[1, 2, 3, 4]);
2460        bv.push_chunk(&[5, 6, 7, 8]);
2461        bv.push(true);
2462        bv.push(false);
2463        bv.push(true);
2464
2465        // Bitmap has 2 full chunks + 3 bits in partial chunk
2466        assert_eq!(bv.len(), 67);
2467
2468        // Prune all chunks (this leaves chunks empty, triggering the reset path)
2469        bv.prune_chunks(3);
2470
2471        // Regression test: len() should be 0, not the old next_bit value (3)
2472        assert_eq!(bv.len(), 0);
2473        assert!(bv.is_empty());
2474
2475        // Bitmap should behave as freshly created
2476        bv.push(true);
2477        assert_eq!(bv.len(), 1);
2478        assert!(bv.get(0));
2479    }
2480
2481    #[test]
2482    fn test_is_chunk_aligned() {
2483        // Empty bitmap is chunk aligned
2484        let bv: BitMap<4> = BitMap::new();
2485        assert!(bv.is_chunk_aligned());
2486
2487        // Test with various chunk sizes
2488        let mut bv4: BitMap<4> = BitMap::new();
2489        assert!(bv4.is_chunk_aligned());
2490
2491        // Add bits one at a time and check alignment
2492        for i in 1..=32 {
2493            bv4.push(i % 2 == 0);
2494            if i == 32 {
2495                assert!(bv4.is_chunk_aligned()); // Exactly one chunk
2496            } else {
2497                assert!(!bv4.is_chunk_aligned()); // Partial chunk
2498            }
2499        }
2500
2501        // Add more bits
2502        for i in 33..=64 {
2503            bv4.push(i % 2 == 0);
2504            if i == 64 {
2505                assert!(bv4.is_chunk_aligned()); // Exactly two chunks
2506            } else {
2507                assert!(!bv4.is_chunk_aligned()); // Partial chunk
2508            }
2509        }
2510
2511        // Test with push_chunk
2512        let mut bv: BitMap<8> = BitMap::new();
2513        assert!(bv.is_chunk_aligned());
2514        bv.push_chunk(&[0xFF; 8]);
2515        assert!(bv.is_chunk_aligned()); // 64 bits = 1 chunk for N=8
2516        bv.push_chunk(&[0xAA; 8]);
2517        assert!(bv.is_chunk_aligned()); // 128 bits = 2 chunks
2518        bv.push(true);
2519        assert!(!bv.is_chunk_aligned()); // 129 bits = partial chunk
2520
2521        // Test with push_byte
2522        let mut bv: BitMap<4> = BitMap::new();
2523        for _ in 0..4 {
2524            bv.push_byte(0xFF);
2525        }
2526        assert!(bv.is_chunk_aligned()); // 32 bits = 1 chunk for N=4
2527
2528        // Test after pop
2529        bv.pop();
2530        assert!(!bv.is_chunk_aligned()); // 31 bits = partial chunk
2531
2532        // Test with zeroes and ones constructors
2533        let bv_zeroes: BitMap<4> = BitMap::zeroes(64);
2534        assert!(bv_zeroes.is_chunk_aligned());
2535
2536        let bv_ones: BitMap<4> = BitMap::ones(96);
2537        assert!(bv_ones.is_chunk_aligned());
2538
2539        let bv_partial: BitMap<4> = BitMap::zeroes(65);
2540        assert!(!bv_partial.is_chunk_aligned());
2541    }
2542
2543    #[test]
2544    fn test_unprune_restores_length() {
2545        let mut prunable: Prunable<4> = Prunable::new_with_pruned_chunks(1).unwrap();
2546        assert_eq!(prunable.len(), Prunable::<4>::CHUNK_SIZE_BITS);
2547        assert_eq!(prunable.pruned_chunks(), 1);
2548        let chunk = [0xDE, 0xAD, 0xBE, 0xEF];
2549
2550        prunable.unprune_chunks(&[chunk]);
2551
2552        assert_eq!(prunable.pruned_chunks(), 0);
2553        assert_eq!(prunable.len(), Prunable::<4>::CHUNK_SIZE_BITS);
2554        assert_eq!(prunable.get_chunk_containing(0), &chunk);
2555    }
2556
2557    mod proptests {
2558        use super::*;
2559        use proptest::prelude::*;
2560
2561        proptest! {
2562            #[test]
2563            fn is_unset_matches_naive(
2564                bits in prop::collection::vec(any::<bool>(), 1..=512usize),
2565                start in 0u64..=512,
2566                end in 0u64..=512,
2567            ) {
2568                let bitmap: BitMap = BitMap::from(bits.as_slice());
2569                let len = bitmap.len();
2570                let start = start.min(len);
2571                let end = end.max(start).min(len);
2572                let range = start..end;
2573
2574                let expected = range.clone().all(|i| !bitmap.get(i));
2575
2576                prop_assert_eq!(bitmap.is_unset(range), expected);
2577            }
2578        }
2579    }
2580
2581    #[test]
2582    fn is_unset_all_zeros() {
2583        let bitmap = BitMap::<8>::zeroes(256);
2584        assert!(bitmap.is_unset(0..256));
2585    }
2586
2587    #[test]
2588    fn is_unset_all_ones() {
2589        let bitmap = BitMap::<8>::ones(256);
2590        assert!(!bitmap.is_unset(0..256));
2591    }
2592
2593    #[test]
2594    fn is_unset_single_bit() {
2595        let mut bitmap = BitMap::<8>::zeroes(64);
2596        bitmap.set(31, true);
2597        assert!(bitmap.is_unset(0..31));
2598        assert!(!bitmap.is_unset(0..32));
2599        assert!(!bitmap.is_unset(31..32));
2600        assert!(bitmap.is_unset(32..64));
2601    }
2602
2603    #[test]
2604    fn is_unset_empty_range() {
2605        let bitmap = BitMap::<8>::ones(64);
2606        assert!(bitmap.is_unset(0..0));
2607        assert!(bitmap.is_unset(32..32));
2608        assert!(bitmap.is_unset(64..64));
2609    }
2610
2611    #[test]
2612    fn is_unset_chunk_boundaries() {
2613        // N=1 means 8 bits per chunk, so boundaries are more frequent
2614        let mut bitmap = BitMap::<1>::zeroes(32);
2615        bitmap.set(7, true);
2616        assert!(bitmap.is_unset(0..7));
2617        assert!(!bitmap.is_unset(0..8));
2618        assert!(bitmap.is_unset(8..32));
2619    }
2620
2621    #[test]
2622    fn is_unset_small_chunk_multi_span() {
2623        // N=4 means 32 bits per chunk, test spanning 3 chunks
2624        let mut bitmap = BitMap::<4>::zeroes(128);
2625        bitmap.set(96, true);
2626        assert!(bitmap.is_unset(0..96));
2627        assert!(!bitmap.is_unset(0..97));
2628        assert!(bitmap.is_unset(97..128));
2629    }
2630
2631    #[test]
2632    #[should_panic(expected = "out of bounds")]
2633    fn is_unset_out_of_bounds() {
2634        let bitmap = BitMap::<8>::zeroes(64);
2635        bitmap.is_unset(0..65);
2636    }
2637
2638    #[cfg(feature = "arbitrary")]
2639    mod conformance {
2640        use super::*;
2641        use commonware_codec::conformance::CodecConformance;
2642
2643        commonware_conformance::conformance_tests! {
2644            CodecConformance<BitMap>
2645        }
2646    }
2647}