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