Skip to main content

vortex_buffer/bit/
buf_mut.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use std::ops::Not;
5
6use arrow_buffer::bit_chunk_iterator::BitChunks;
7use arrow_buffer::bit_chunk_iterator::UnalignedBitChunk;
8use bitvec::view::BitView;
9
10use crate::BitBuffer;
11use crate::BufferMut;
12use crate::ByteBufferMut;
13use crate::bit::get_bit_unchecked;
14use crate::bit::ops;
15use crate::bit::set_bit_unchecked;
16use crate::bit::unset_bit_unchecked;
17use crate::buffer_mut;
18
19/// Sets all bits in the bit-range `[start_bit, end_bit)` of `slice` to `value`.
20#[inline(always)]
21fn fill_bits(slice: &mut [u8], start_bit: usize, end_bit: usize, value: bool) {
22    if start_bit >= end_bit {
23        return;
24    }
25
26    let fill_byte: u8 = if value { 0xFF } else { 0x00 };
27
28    let start_byte = start_bit / 8;
29    let start_rem = start_bit % 8;
30    let end_byte = end_bit / 8;
31    let end_rem = end_bit % 8;
32
33    if start_byte == end_byte {
34        // All bits are in the same byte
35        let mask = ((1u8 << (end_rem - start_rem)) - 1) << start_rem;
36        if value {
37            slice[start_byte] |= mask;
38        } else {
39            slice[start_byte] &= !mask;
40        }
41    } else {
42        // First partial byte
43        if start_rem != 0 {
44            let mask = !((1u8 << start_rem) - 1);
45            if value {
46                slice[start_byte] |= mask;
47            } else {
48                slice[start_byte] &= !mask;
49            }
50        }
51
52        // Middle bytes
53        let fill_start = if start_rem != 0 {
54            start_byte + 1
55        } else {
56            start_byte
57        };
58        if fill_start < end_byte {
59            slice[fill_start..end_byte].fill(fill_byte);
60        }
61
62        // Last partial byte
63        if end_rem != 0 {
64            let mask = (1u8 << end_rem) - 1;
65            if value {
66                slice[end_byte] |= mask;
67            } else {
68                slice[end_byte] &= !mask;
69            }
70        }
71    }
72}
73
74/// A mutable bitset buffer that allows random access to individual bits for set and get.
75///
76///
77/// # Example
78/// ```
79/// use vortex_buffer::BitBufferMut;
80///
81/// let mut bools = BitBufferMut::new_unset(10);
82/// bools.set_to(9, true);
83/// for i in 0..9 {
84///    assert!(!bools.value(i));
85/// }
86/// assert!(bools.value(9));
87///
88/// // Freeze into a new bools vector.
89/// let bools = bools.freeze();
90/// ```
91///
92/// See also: [`BitBuffer`].
93#[derive(Debug, Clone, Eq)]
94pub struct BitBufferMut {
95    buffer: ByteBufferMut,
96    /// Represents the offset of the bit buffer into the first byte.
97    ///
98    /// This is always less than 8 (for when the bit buffer is not aligned to a byte).
99    offset: usize,
100    len: usize,
101}
102
103impl PartialEq for BitBufferMut {
104    fn eq(&self, other: &Self) -> bool {
105        if self.len != other.len {
106            return false;
107        }
108
109        self.chunks()
110            .iter_padded()
111            .zip(other.chunks().iter_padded())
112            .all(|(a, b)| a == b)
113    }
114}
115
116impl BitBufferMut {
117    /// Create new bit buffer from given byte buffer and logical bit length
118    pub fn from_buffer(buffer: ByteBufferMut, offset: usize, len: usize) -> Self {
119        assert!(
120            len <= buffer.len() * 8,
121            "Buffer len {} is too short for the given length {len}",
122            buffer.len()
123        );
124        Self {
125            buffer,
126            offset,
127            len,
128        }
129    }
130
131    /// Creates a `BitBufferMut` from a [`BitBuffer`] by copying all of the data over.
132    pub fn copy_from(bit_buffer: &BitBuffer) -> Self {
133        Self {
134            buffer: ByteBufferMut::copy_from(bit_buffer.inner()),
135            offset: bit_buffer.offset(),
136            len: bit_buffer.len(),
137        }
138    }
139
140    /// Create a new empty mutable bit buffer with requested capacity (in bits).
141    pub fn with_capacity(capacity: usize) -> Self {
142        Self {
143            buffer: BufferMut::with_capacity(capacity.div_ceil(8)),
144            offset: 0,
145            len: 0,
146        }
147    }
148
149    /// Create a new mutable buffer with requested `len` and all bits set to `true`.
150    pub fn new_set(len: usize) -> Self {
151        Self {
152            buffer: buffer_mut![0xFF; len.div_ceil(8)],
153            offset: 0,
154            len,
155        }
156    }
157
158    /// Create a new mutable buffer with requested `len` and all bits set to `false`.
159    pub fn new_unset(len: usize) -> Self {
160        Self {
161            buffer: BufferMut::zeroed(len.div_ceil(8)),
162            offset: 0,
163            len,
164        }
165    }
166
167    /// Create a new empty `BitBufferMut`.
168    #[inline(always)]
169    pub fn empty() -> Self {
170        Self::with_capacity(0)
171    }
172
173    /// Create a new mutable buffer with requested `len` and all bits set to `value`.
174    pub fn full(value: bool, len: usize) -> Self {
175        if value {
176            Self::new_set(len)
177        } else {
178            Self::new_unset(len)
179        }
180    }
181
182    /// Create a bit buffer of `len` with `indices` set as true.
183    pub fn from_indices(len: usize, indices: &[usize]) -> BitBufferMut {
184        let mut buf = BitBufferMut::new_unset(len);
185        // TODO(ngates): for dense indices, we can do better by collecting into u64s.
186        indices.iter().for_each(|&idx| buf.set(idx));
187        buf
188    }
189
190    /// Invokes `f` with indexes `0..len` collecting the boolean results into a new `BitBufferMut`
191    #[inline]
192    pub fn collect_bool<F: FnMut(usize) -> bool>(len: usize, mut f: F) -> Self {
193        let mut buffer = BufferMut::with_capacity(len.div_ceil(64) * 8);
194
195        let chunks = len / 64;
196        let remainder = len % 64;
197        for chunk in 0..chunks {
198            let mut packed = 0;
199            for bit_idx in 0..64 {
200                let i = bit_idx + chunk * 64;
201                packed |= (f(i) as u64) << bit_idx;
202            }
203
204            // SAFETY: Already allocated sufficient capacity
205            unsafe { buffer.push_unchecked(packed) }
206        }
207
208        if remainder != 0 {
209            let mut packed = 0;
210            for bit_idx in 0..remainder {
211                let i = bit_idx + chunks * 64;
212                packed |= (f(i) as u64) << bit_idx;
213            }
214
215            // SAFETY: Already allocated sufficient capacity
216            unsafe { buffer.push_unchecked(packed) }
217        }
218
219        buffer.truncate(len.div_ceil(8));
220
221        Self {
222            buffer: buffer.into_byte_buffer(),
223            offset: 0,
224            len,
225        }
226    }
227
228    /// Return the underlying byte buffer.
229    pub fn inner(&self) -> &ByteBufferMut {
230        &self.buffer
231    }
232
233    /// Consumes the buffer and return the underlying byte buffer.
234    pub fn into_inner(self) -> ByteBufferMut {
235        self.buffer
236    }
237
238    /// Get the current populated length of the buffer.
239    #[inline(always)]
240    pub fn len(&self) -> usize {
241        self.len
242    }
243
244    /// True if the buffer has length 0.
245    #[inline(always)]
246    pub fn is_empty(&self) -> bool {
247        self.len == 0
248    }
249
250    /// Get the current bit offset of the buffer.
251    #[inline(always)]
252    pub fn offset(&self) -> usize {
253        self.offset
254    }
255
256    /// Get the value at the requested index.
257    #[inline(always)]
258    pub fn value(&self, index: usize) -> bool {
259        assert!(index < self.len);
260        // SAFETY: checked by assertion
261        unsafe { self.value_unchecked(index) }
262    }
263
264    /// Get the value at the requested index without bounds checking.
265    ///
266    /// # Safety
267    ///
268    /// The caller must ensure that `index` is less than the length of the buffer.
269    #[inline(always)]
270    pub unsafe fn value_unchecked(&self, index: usize) -> bool {
271        unsafe { get_bit_unchecked(self.buffer.as_ptr(), self.offset + index) }
272    }
273
274    /// Access chunks of the underlying buffer as 8 byte chunks with a final trailer
275    ///
276    /// If you're performing operations on a single buffer, prefer [BitBuffer::unaligned_chunks]
277    pub fn chunks(&self) -> BitChunks<'_> {
278        BitChunks::new(self.buffer.as_slice(), self.offset, self.len)
279    }
280
281    /// Get the bit capacity of the buffer.
282    #[inline(always)]
283    pub fn capacity(&self) -> usize {
284        (self.buffer.capacity() * 8) - self.offset
285    }
286
287    /// Reserve additional bit capacity for the buffer.
288    pub fn reserve(&mut self, additional: usize) {
289        let required_bits = self.offset + self.len + additional;
290        let required_bytes = required_bits.div_ceil(8); // Rounds up.
291
292        let additional_bytes = required_bytes.saturating_sub(self.buffer.len());
293        self.buffer.reserve(additional_bytes);
294    }
295
296    /// Clears the bit buffer (but keeps any allocated memory).
297    pub fn clear(&mut self) {
298        // Since there are no items we need to drop, we simply set the length to 0.
299        self.len = 0;
300        self.offset = 0;
301    }
302
303    /// Set the bit at `index` to the given boolean value.
304    ///
305    /// This operation is checked so if `index` exceeds the buffer length, this will panic.
306    pub fn set_to(&mut self, index: usize, value: bool) {
307        if value {
308            self.set(index);
309        } else {
310            self.unset(index);
311        }
312    }
313
314    /// Set the bit at `index` to the given boolean value without checking bounds.
315    ///
316    /// # Safety
317    ///
318    /// The caller must ensure that `index` does not exceed the largest bit index in the backing buffer.
319    pub unsafe fn set_to_unchecked(&mut self, index: usize, value: bool) {
320        if value {
321            // SAFETY: checked by caller
322            unsafe { self.set_unchecked(index) }
323        } else {
324            // SAFETY: checked by caller
325            unsafe { self.unset_unchecked(index) }
326        }
327    }
328
329    /// Set a position to `true`.
330    ///
331    /// This operation is checked so if `index` exceeds the buffer length, this will panic.
332    pub fn set(&mut self, index: usize) {
333        assert!(index < self.len, "index {index} exceeds len {}", self.len);
334
335        // SAFETY: checked by assertion
336        unsafe { self.set_unchecked(index) };
337    }
338
339    /// Set a position to `false`.
340    ///
341    /// This operation is checked so if `index` exceeds the buffer length, this will panic.
342    #[inline]
343    pub fn unset(&mut self, index: usize) {
344        assert!(index < self.len, "index {index} exceeds len {}", self.len);
345
346        // SAFETY: checked by assertion
347        unsafe { self.unset_unchecked(index) };
348    }
349
350    /// Set the bit at `index` to `true` without checking bounds.
351    ///
352    /// Note: Do not call this in a tight loop. Prefer to use [`set_bit_unchecked`].
353    ///
354    /// # Safety
355    ///
356    /// The caller must ensure that `index` does not exceed the largest bit index in the backing buffer.
357    unsafe fn set_unchecked(&mut self, index: usize) {
358        // SAFETY: checked by caller
359        unsafe { set_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
360    }
361
362    /// Unset the bit at `index` without checking bounds.
363    ///
364    /// Note: Do not call this in a tight loop. Prefer to use [`unset_bit_unchecked`].
365    ///
366    /// # Safety
367    ///
368    /// The caller must ensure that `index` does not exceed the largest bit index in the backing buffer.
369    #[inline]
370    pub unsafe fn unset_unchecked(&mut self, index: usize) {
371        // SAFETY: checked by caller
372        unsafe { unset_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
373    }
374
375    /// Foces the length of the `BitBufferMut` to `new_len`.
376    ///
377    /// # Safety
378    ///
379    /// - `new_len` must be less than or equal to [`capacity()`](Self::capacity)
380    /// - The elements at `old_len..new_len` must be initialized
381    #[inline(always)]
382    pub unsafe fn set_len(&mut self, new_len: usize) {
383        debug_assert!(
384            new_len <= self.capacity(),
385            "`set_len` requires that new_len <= capacity()"
386        );
387
388        // Calculate the new byte length required to hold the bits
389        let bytes_len = (self.offset + new_len).div_ceil(8);
390        unsafe { self.buffer.set_len(bytes_len) };
391
392        self.len = new_len;
393    }
394
395    /// Truncate the buffer to the given length.
396    ///
397    /// If the given length is greater than the current length, this is a no-op.
398    pub fn truncate(&mut self, len: usize) {
399        if len > self.len {
400            return;
401        }
402
403        let new_len_bytes = (self.offset + len).div_ceil(8);
404        self.buffer.truncate(new_len_bytes);
405        self.len = len;
406    }
407
408    /// Append a new boolean into the bit buffer, incrementing the length.
409    pub fn append(&mut self, value: bool) {
410        if value {
411            self.append_true()
412        } else {
413            self.append_false()
414        }
415    }
416
417    /// Append a new true value to the buffer.
418    pub fn append_true(&mut self) {
419        let bit_pos = self.offset + self.len;
420        let byte_pos = bit_pos / 8;
421        let bit_in_byte = bit_pos % 8;
422
423        // Ensure buffer has enough bytes
424        if byte_pos >= self.buffer.len() {
425            self.buffer.push(0u8);
426        }
427
428        // Set the bit
429        self.buffer.as_mut_slice()[byte_pos] |= 1 << bit_in_byte;
430        self.len += 1;
431    }
432
433    /// Append a new false value to the buffer.
434    pub fn append_false(&mut self) {
435        let bit_pos = self.offset + self.len;
436        let byte_pos = bit_pos / 8;
437        let bit_in_byte = bit_pos % 8;
438
439        // Ensure buffer has enough bytes
440        if byte_pos >= self.buffer.len() {
441            self.buffer.push(0u8);
442        }
443
444        // Bit is already 0 if we just pushed a new byte, otherwise ensure it's unset
445        if bit_in_byte != 0 {
446            self.buffer.as_mut_slice()[byte_pos] &= !(1 << bit_in_byte);
447        }
448
449        self.len += 1;
450    }
451
452    /// Append several boolean values into the bit buffer. After this operation,
453    /// the length will be incremented by `n`.
454    ///
455    /// Panics if the buffer does not have `n` slots left.
456    #[inline]
457    pub fn append_n(&mut self, value: bool, n: usize) {
458        if n == 0 {
459            return;
460        }
461
462        let end_bit_pos = self.offset + self.len + n;
463        let required_bytes = end_bit_pos.div_ceil(8);
464
465        // Ensure buffer has enough bytes
466        if required_bytes > self.buffer.len() {
467            self.buffer.push_n(0x00, required_bytes - self.buffer.len());
468        }
469
470        let start = self.len;
471        self.len += n;
472        self.fill_range(start, self.len, value);
473    }
474
475    /// Sets all bits in the range `[start, end)` to `value`.
476    ///
477    /// This operates on an arbitrary range within the existing length of the buffer.
478    /// Panics if `end > self.len` or `start > end`.
479    #[inline(always)]
480    pub fn fill_range(&mut self, start: usize, end: usize, value: bool) {
481        assert!(end <= self.len, "end {end} exceeds len {}", self.len);
482        assert!(start <= end, "start {start} exceeds end {end}");
483
484        // SAFETY: assertions above guarantee start <= end <= self.len,
485        // so offset + end fits within the buffer.
486        unsafe { self.fill_range_unchecked(start, end, value) }
487    }
488
489    /// Sets all bits in the range `[start, end)` to `value` without bounds checking.
490    ///
491    /// # Safety
492    ///
493    /// The caller must ensure that `start <= end <= self.len`.
494    #[inline(always)]
495    pub unsafe fn fill_range_unchecked(&mut self, start: usize, end: usize, value: bool) {
496        fill_bits(
497            self.buffer.as_mut_slice(),
498            self.offset + start,
499            self.offset + end,
500            value,
501        );
502    }
503
504    /// Append a [`BitBuffer`] to this [`BitBufferMut`]
505    ///
506    /// This efficiently copies all bits from the source buffer to the end of this buffer.
507    pub fn append_buffer(&mut self, buffer: &BitBuffer) {
508        let bit_len = buffer.len();
509        if bit_len == 0 {
510            return;
511        }
512
513        let start_bit_pos = self.offset + self.len;
514        let end_bit_pos = start_bit_pos + bit_len;
515        let required_bytes = end_bit_pos.div_ceil(8);
516
517        // Ensure buffer has enough bytes
518        if required_bytes > self.buffer.len() {
519            self.buffer.push_n(0x00, required_bytes - self.buffer.len());
520        }
521
522        // Use bitvec for efficient bit copying
523        let self_slice = self
524            .buffer
525            .as_mut_slice()
526            .view_bits_mut::<bitvec::prelude::Lsb0>();
527        let other_slice = buffer
528            .inner()
529            .as_slice()
530            .view_bits::<bitvec::prelude::Lsb0>();
531
532        // Copy from source buffer (accounting for its offset) to destination (accounting for our offset + len)
533        let source_range = buffer.offset()..buffer.offset() + bit_len;
534        self_slice[start_bit_pos..end_bit_pos].copy_from_bitslice(&other_slice[source_range]);
535
536        self.len += bit_len;
537    }
538
539    /// Splits the bit buffer into two at the given index.
540    ///
541    /// Afterward, self contains elements `[0, at)`, and the returned buffer contains elements
542    /// `[at, capacity)`.
543    ///
544    /// Unlike bytes, if the split position is not on a byte-boundary this operation will copy
545    /// data into the result type, and mutate self.
546    #[must_use = "consider BitBufferMut::truncate if you don't need the other half"]
547    pub fn split_off(&mut self, at: usize) -> Self {
548        assert!(
549            at <= self.capacity(),
550            "index {at} exceeds capacity {}",
551            self.capacity()
552        );
553
554        // The length of the tail is any bits after `at`
555        let tail_len = self.len.saturating_sub(at);
556        let byte_pos = (self.offset + at).div_ceil(8);
557
558        // If we are splitting on a byte boundary, we can just slice the buffer
559        // Or if `at > self.len`, then the tail is empty anyway and we can just return as much
560        // of the existing capacity as possible.
561        if at > self.len() || (self.offset + at).is_multiple_of(8) {
562            let tail_buffer = self.buffer.split_off(byte_pos);
563            self.len = self.len.min(at);
564
565            // Return the tail buffer
566            return Self {
567                buffer: tail_buffer,
568                offset: 0,
569                len: tail_len,
570            };
571        }
572
573        // Otherwise, we truncate ourselves, and copy any bits into a new tail buffer.
574        // Note that in this case we do not preserve the capacity.
575        let u64_cap = tail_len.div_ceil(8);
576        let mut tail_buffer_u64 = BufferMut::<u64>::with_capacity(u64_cap);
577        tail_buffer_u64.extend(
578            BitChunks::new(self.buffer.as_slice(), self.offset + at, tail_len).iter_padded(),
579        );
580
581        self.truncate(at);
582        BitBufferMut::from_buffer(tail_buffer_u64.into_byte_buffer(), 0, tail_len)
583    }
584
585    /// Absorbs a mutable buffer that was previously split off.
586    ///
587    /// If the two buffers were previously contiguous and not mutated in a way that causes
588    /// re-allocation i.e., if other was created by calling split_off on this buffer, then this is
589    /// an O(1) operation that just decreases a reference count and sets a few indices.
590    ///
591    /// Otherwise, this method degenerates to self.append_buffer(&other).
592    pub fn unsplit(&mut self, other: Self) {
593        if (self.offset + self.len).is_multiple_of(8) && other.offset == 0 {
594            // We are aligned and can just append the buffers
595            self.buffer.unsplit(other.buffer);
596            self.len += other.len;
597            return;
598        }
599
600        // Otherwise, we need to append the bits one by one
601        self.append_buffer(&other.freeze())
602    }
603
604    /// Freeze the buffer in its current state into an immutable `BoolBuffer`.
605    pub fn freeze(self) -> BitBuffer {
606        BitBuffer::new_with_offset(self.buffer.freeze(), self.len, self.offset)
607    }
608
609    /// Get the underlying bytes as a slice
610    pub fn as_slice(&self) -> &[u8] {
611        self.buffer.as_slice()
612    }
613
614    /// Get the underlying bytes as a mutable slice
615    pub fn as_mut_slice(&mut self) -> &mut [u8] {
616        self.buffer.as_mut_slice()
617    }
618
619    /// Returns a raw mutable pointer to the internal buffer.
620    pub fn as_mut_ptr(&mut self) -> *mut u8 {
621        self.buffer.as_mut_ptr()
622    }
623
624    /// Access chunks of the buffer aligned to 8 byte boundary as [prefix, \<full chunks\>, suffix]
625    pub fn unaligned_chunks(&self) -> UnalignedBitChunk<'_> {
626        UnalignedBitChunk::new(self.buffer.as_slice(), self.offset, self.len)
627    }
628
629    /// Get the number of set bits in the buffer.
630    pub fn true_count(&self) -> usize {
631        self.unaligned_chunks().count_ones()
632    }
633
634    /// Get the number of unset bits in the buffer.
635    pub fn false_count(&self) -> usize {
636        self.len - self.true_count()
637    }
638}
639
640impl Default for BitBufferMut {
641    fn default() -> Self {
642        Self::with_capacity(0)
643    }
644}
645
646// Mutate-in-place implementation of bitwise NOT.
647impl Not for BitBufferMut {
648    type Output = BitBufferMut;
649
650    #[inline]
651    fn not(mut self) -> Self::Output {
652        ops::bitwise_unary_op_mut(&mut self, |b| !b);
653        self
654    }
655}
656
657impl From<&[bool]> for BitBufferMut {
658    fn from(value: &[bool]) -> Self {
659        BitBuffer::collect_bool(value.len(), |i| value[i]).into_mut()
660    }
661}
662
663impl From<Vec<bool>> for BitBufferMut {
664    fn from(value: Vec<bool>) -> Self {
665        value.as_slice().into()
666    }
667}
668
669impl FromIterator<bool> for BitBufferMut {
670    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
671        let mut iter = iter.into_iter();
672
673        // Since we do not know the length of the iterator, we can only guess how much memory we
674        // need to reserve. Note that these hints may be inaccurate.
675        let (lower_bound, _) = iter.size_hint();
676
677        // We choose not to use the optional upper bound size hint to match the standard library.
678
679        // Initialize all bits to 0 with the given length. By doing this, we only need to set bits
680        // that are true (and this is faster from benchmarks).
681        let mut buf = BitBufferMut::new_unset(lower_bound);
682        assert_eq!(buf.offset, 0);
683
684        // Directly write within our known capacity.
685        let ptr = buf.buffer.as_mut_ptr();
686        for i in 0..lower_bound {
687            let Some(v) = iter.next() else {
688                // SAFETY: We are definitely under the capacity and all values are already
689                // initialized from `new_unset`.
690                unsafe { buf.set_len(i) };
691                return buf;
692            };
693
694            if v {
695                // SAFETY: We have ensured that we are within the capacity.
696                unsafe { set_bit_unchecked(ptr, i) }
697            }
698        }
699
700        // Append the remaining items (as we do not know how many more there are).
701        for v in iter {
702            buf.append(v);
703        }
704
705        buf
706    }
707}
708
709#[cfg(test)]
710mod tests {
711    use crate::BufferMut;
712    use crate::bit::buf_mut::BitBufferMut;
713    use crate::bitbuffer;
714    use crate::bitbuffer_mut;
715    use crate::buffer_mut;
716
717    #[test]
718    fn test_bits_mut() {
719        let mut bools = bitbuffer_mut![false; 10];
720        bools.set_to(0, true);
721        bools.set_to(9, true);
722
723        let bools = bools.freeze();
724        assert!(bools.value(0));
725        for i in 1..=8 {
726            assert!(!bools.value(i));
727        }
728        assert!(bools.value(9));
729    }
730
731    #[test]
732    fn test_append_n() {
733        let mut bools = BitBufferMut::with_capacity(10);
734        assert_eq!(bools.len(), 0);
735        assert!(bools.is_empty());
736
737        bools.append(true);
738        bools.append_n(false, 8);
739        bools.append_n(true, 1);
740
741        let bools = bools.freeze();
742
743        assert_eq!(bools.true_count(), 2);
744        assert!(bools.value(0));
745        assert!(bools.value(9));
746    }
747
748    #[test]
749    fn test_reserve_ensures_len_plus_additional() {
750        // This test documents the fix for the bug where reserve was incorrectly
751        // calculating additional bytes from capacity instead of len.
752
753        let mut bits = BitBufferMut::with_capacity(10);
754        assert_eq!(bits.len(), 0);
755
756        bits.reserve(100);
757
758        // Should have capacity for at least len + 100 = 0 + 100 = 100 bits.
759        assert!(bits.capacity() >= 100);
760
761        bits.append_n(true, 50);
762        assert_eq!(bits.len(), 50);
763
764        bits.reserve(100);
765
766        // Should have capacity for at least len + 100 = 50 + 100 = 150 bits.
767        assert!(bits.capacity() >= 150);
768    }
769
770    #[test]
771    fn test_with_offset_zero() {
772        // Test basic operations when offset is 0
773        let buf = BufferMut::zeroed(2);
774        let mut bit_buf = BitBufferMut::from_buffer(buf, 0, 16);
775
776        // Set some bits
777        bit_buf.set(0);
778        bit_buf.set(7);
779        bit_buf.set(8);
780        bit_buf.set(15);
781
782        // Verify values
783        assert!(bit_buf.value(0));
784        assert!(bit_buf.value(7));
785        assert!(bit_buf.value(8));
786        assert!(bit_buf.value(15));
787        assert!(!bit_buf.value(1));
788        assert!(!bit_buf.value(9));
789
790        // Verify underlying bytes
791        assert_eq!(bit_buf.as_slice()[0], 0b10000001);
792        assert_eq!(bit_buf.as_slice()[1], 0b10000001);
793    }
794
795    #[test]
796    fn test_with_offset_within_byte() {
797        // Test operations with offset=3 (within first byte)
798        let buf = buffer_mut![0b11111111, 0b00000000, 0b00000000];
799        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 10);
800
801        // Initially, bits 3-7 from first byte are set (5 bits)
802        // and bits 0-4 from second byte are unset (5 bits more)
803        assert!(bit_buf.value(0)); // bit 3 of byte 0
804        assert!(bit_buf.value(4)); // bit 7 of byte 0
805        assert!(!bit_buf.value(5)); // bit 0 of byte 1
806
807        // Set a bit in the second byte's range
808        bit_buf.set(7);
809        assert!(bit_buf.value(7));
810
811        // Unset a bit in the first byte's range
812        bit_buf.unset(0);
813        assert!(!bit_buf.value(0));
814    }
815
816    #[test]
817    fn test_with_offset_byte_boundary() {
818        // Test operations with offset=8 (exactly one byte)
819        let buf = buffer_mut![0xFF, 0x00, 0xFF];
820        let mut bit_buf = BitBufferMut::from_buffer(buf, 8, 16);
821
822        // Buffer starts at byte 1, so all bits should be unset initially
823        for i in 0..8 {
824            assert!(!bit_buf.value(i));
825        }
826        // Next byte has all bits set
827        for i in 8..16 {
828            assert!(bit_buf.value(i));
829        }
830
831        // Set some bits
832        bit_buf.set(0);
833        bit_buf.set(3);
834        assert!(bit_buf.value(0));
835        assert!(bit_buf.value(3));
836    }
837
838    #[test]
839    fn test_with_large_offset() {
840        // Test with offset=13 (one byte + 5 bits)
841        let buf = buffer_mut![0xFF, 0xFF, 0xFF, 0xFF];
842        let mut bit_buf = BitBufferMut::from_buffer(buf, 13, 10);
843
844        // All bits should initially be set
845        for i in 0..10 {
846            assert!(bit_buf.value(i));
847        }
848
849        // Unset some bits
850        bit_buf.unset(0);
851        bit_buf.unset(5);
852        bit_buf.unset(9);
853
854        assert!(!bit_buf.value(0));
855        assert!(bit_buf.value(1));
856        assert!(!bit_buf.value(5));
857        assert!(!bit_buf.value(9));
858    }
859
860    #[test]
861    fn test_append_with_offset() {
862        // Create buffer with offset
863        let buf = buffer_mut![0b11100000]; // First 3 bits unset, last 5 set
864        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0); // Start at bit 3, len=0
865
866        // Append some bits
867        bit_buf.append(false); // Should use bit 3
868        bit_buf.append(true); // Should use bit 4
869        bit_buf.append(true); // Should use bit 5
870
871        assert_eq!(bit_buf.len(), 3);
872        assert!(!bit_buf.value(0));
873        assert!(bit_buf.value(1));
874        assert!(bit_buf.value(2));
875    }
876
877    #[test]
878    fn test_append_n_with_offset_crossing_boundary() {
879        // Create buffer with offset that will cross byte boundary when appending
880        let buf = BufferMut::zeroed(4);
881        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
882
883        // Append enough bits to cross into next byte
884        bit_buf.append_n(true, 10); // 5 bits left in first byte, then 5 in second
885
886        assert_eq!(bit_buf.len(), 10);
887        for i in 0..10 {
888            assert!(bit_buf.value(i));
889        }
890
891        // Verify the underlying bytes
892        // Bits 5-7 of byte 0 should be set (3 bits)
893        // Bits 0-6 of byte 1 should be set (7 bits)
894        assert_eq!(bit_buf.as_slice()[0], 0b11100000);
895        assert_eq!(bit_buf.as_slice()[1], 0b01111111);
896    }
897
898    #[test]
899    fn test_truncate_with_offset() {
900        let buf = buffer_mut![0xFF, 0xFF];
901        let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 12);
902
903        assert_eq!(bit_buf.len(), 12);
904
905        // Truncate to 8 bits
906        bit_buf.truncate(8);
907        assert_eq!(bit_buf.len(), 8);
908
909        // Truncate to 3 bits
910        bit_buf.truncate(3);
911        assert_eq!(bit_buf.len(), 3);
912
913        // Truncating to larger length should be no-op
914        bit_buf.truncate(10);
915        assert_eq!(bit_buf.len(), 3);
916    }
917
918    #[test]
919    fn test_capacity_with_offset() {
920        // Use exact buffer size to test capacity calculation
921        let buf = buffer_mut![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // Exactly 10 bytes = 80 bits
922        let bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
923
924        // Capacity should be at least buffer length minus offset
925        // (may be more due to allocator rounding)
926        assert!(bit_buf.capacity() >= 75);
927        // And should account for offset
928        assert_eq!(bit_buf.capacity() % 8, (80 - 5) % 8);
929    }
930
931    #[test]
932    fn test_reserve_with_offset() {
933        // Use exact buffer to test reserve
934        let buf = buffer_mut![0, 0]; // Exactly 2 bytes = 16 bits
935        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
936
937        // Current capacity should be at least 13 bits (16 - 3)
938        let initial_capacity = bit_buf.capacity();
939        assert!(initial_capacity >= 13);
940
941        // Reserve 20 more bits (need total of offset 3 + len 0 + additional 20 = 23 bits)
942        bit_buf.reserve(20);
943
944        // Should now have at least 20 bits of capacity
945        assert!(bit_buf.capacity() >= 20);
946    }
947
948    #[test]
949    fn test_freeze_with_offset() {
950        let buf = buffer_mut![0b11110000, 0b00001111];
951        let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
952
953        // Set some bits
954        bit_buf.set(0);
955        bit_buf.set(7);
956
957        // Freeze and verify offset is preserved
958        let frozen = bit_buf.freeze();
959        assert_eq!(frozen.offset(), 4);
960        assert_eq!(frozen.len(), 8);
961
962        // Verify values through frozen buffer
963        assert!(frozen.value(0));
964        assert!(frozen.value(7));
965    }
966
967    #[cfg_attr(miri, ignore)] // bitvec crate uses a ptr cast that Miri doesn't support
968    #[test]
969    fn test_append_buffer_with_offsets() {
970        // Create source buffer with offset
971        let source = bitbuffer![false, false, true, true, false, true];
972
973        // Create destination buffer with offset
974        let buf = BufferMut::zeroed(4);
975        let mut dest = BitBufferMut::from_buffer(buf, 3, 0);
976
977        // Append 2 initial bits
978        dest.append(true);
979        dest.append(false);
980
981        // Append the source buffer
982        dest.append_buffer(&source);
983
984        assert_eq!(dest.len(), 8);
985        assert!(dest.value(0)); // Our first append
986        assert!(!dest.value(1)); // Our second append
987        assert!(!dest.value(2)); // From source[0]
988        assert!(!dest.value(3)); // From source[1]
989        assert!(dest.value(4)); // From source[2]
990        assert!(dest.value(5)); // From source[3]
991        assert!(!dest.value(6)); // From source[4]
992        assert!(dest.value(7)); // From source[5]
993    }
994
995    #[test]
996    fn test_set_unset_unchecked_with_offset() {
997        let buf = BufferMut::zeroed(3);
998        let mut bit_buf = BitBufferMut::from_buffer(buf, 7, 10);
999
1000        unsafe {
1001            bit_buf.set_unchecked(0);
1002            bit_buf.set_unchecked(5);
1003            bit_buf.set_unchecked(9);
1004        }
1005
1006        assert!(bit_buf.value(0));
1007        assert!(bit_buf.value(5));
1008        assert!(bit_buf.value(9));
1009
1010        unsafe {
1011            bit_buf.unset_unchecked(5);
1012        }
1013
1014        assert!(!bit_buf.value(5));
1015    }
1016
1017    #[test]
1018    fn test_value_unchecked_with_offset() {
1019        let buf = buffer_mut![0b11110000, 0b00001111];
1020        let bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
1021
1022        unsafe {
1023            // First 4 bits of logical buffer come from bits 4-7 of first byte (all 1s)
1024            assert!(bit_buf.value_unchecked(0));
1025            assert!(bit_buf.value_unchecked(3));
1026
1027            // Next 4 bits come from bits 0-3 of second byte (all 1s)
1028            assert!(bit_buf.value_unchecked(4));
1029            assert!(bit_buf.value_unchecked(7));
1030        }
1031    }
1032
1033    #[test]
1034    fn test_append_alternating_with_offset() {
1035        let buf = BufferMut::zeroed(4);
1036        let mut bit_buf = BitBufferMut::from_buffer(buf, 2, 0);
1037
1038        // Append alternating pattern across byte boundaries
1039        for i in 0..20 {
1040            bit_buf.append(i % 2 == 0);
1041        }
1042
1043        assert_eq!(bit_buf.len(), 20);
1044        for i in 0..20 {
1045            assert_eq!(bit_buf.value(i), i % 2 == 0);
1046        }
1047    }
1048
1049    #[test]
1050    fn test_new_set_new_unset() {
1051        let set_buf = bitbuffer_mut![true; 10];
1052        let unset_buf = bitbuffer_mut![false; 10];
1053
1054        for i in 0..10 {
1055            assert!(set_buf.value(i));
1056            assert!(!unset_buf.value(i));
1057        }
1058
1059        assert_eq!(set_buf.len(), 10);
1060        assert_eq!(unset_buf.len(), 10);
1061    }
1062
1063    #[test]
1064    fn test_append_n_false_with_offset() {
1065        let buf = BufferMut::zeroed(4);
1066        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1067
1068        bit_buf.append_n(false, 15);
1069
1070        assert_eq!(bit_buf.len(), 15);
1071        for i in 0..15 {
1072            assert!(!bit_buf.value(i));
1073        }
1074    }
1075
1076    #[test]
1077    fn test_append_n_true_with_offset() {
1078        let buf = BufferMut::zeroed(4);
1079        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1080
1081        bit_buf.append_n(true, 15);
1082
1083        assert_eq!(bit_buf.len(), 15);
1084        for i in 0..15 {
1085            assert!(bit_buf.value(i));
1086        }
1087    }
1088
1089    #[test]
1090    fn test_mixed_operations_with_offset() {
1091        // Complex test combining multiple operations with offset
1092        let buf = BufferMut::zeroed(5);
1093        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
1094
1095        // Append some bits
1096        bit_buf.append_n(true, 5);
1097        bit_buf.append_n(false, 3);
1098        bit_buf.append(true);
1099
1100        assert_eq!(bit_buf.len(), 9);
1101
1102        // Set and unset
1103        bit_buf.set(6); // Was false, now true
1104        bit_buf.unset(2); // Was true, now false
1105
1106        // Verify
1107        assert!(bit_buf.value(0));
1108        assert!(bit_buf.value(1));
1109        assert!(!bit_buf.value(2)); // Unset
1110        assert!(bit_buf.value(3));
1111        assert!(bit_buf.value(4));
1112        assert!(!bit_buf.value(5));
1113        assert!(bit_buf.value(6)); // Set
1114        assert!(!bit_buf.value(7));
1115        assert!(bit_buf.value(8));
1116
1117        // Truncate
1118        bit_buf.truncate(6);
1119        assert_eq!(bit_buf.len(), 6);
1120
1121        // Freeze and verify offset preserved
1122        let frozen = bit_buf.freeze();
1123        assert_eq!(frozen.offset(), 3);
1124        assert_eq!(frozen.len(), 6);
1125    }
1126
1127    #[test]
1128    fn test_from_iterator_with_incorrect_size_hint() {
1129        // This test catches a bug where FromIterator assumed the upper bound
1130        // from size_hint was accurate. The iterator contract allows the actual
1131        // count to exceed the upper bound, which could cause UB if we used
1132        // append_unchecked beyond the allocated capacity.
1133
1134        // Custom iterator that lies about its size hint.
1135        struct LyingIterator {
1136            values: Vec<bool>,
1137            index: usize,
1138        }
1139
1140        impl Iterator for LyingIterator {
1141            type Item = bool;
1142
1143            fn next(&mut self) -> Option<Self::Item> {
1144                (self.index < self.values.len()).then(|| {
1145                    let val = self.values[self.index];
1146                    self.index += 1;
1147                    val
1148                })
1149            }
1150
1151            fn size_hint(&self) -> (usize, Option<usize>) {
1152                // Deliberately return an incorrect upper bound that's smaller
1153                // than the actual number of elements we'll yield.
1154                let remaining = self.values.len() - self.index;
1155                let lower = remaining.min(5); // Correct lower bound (but capped).
1156                let upper = Some(5); // Incorrect upper bound - we actually have more!
1157                (lower, upper)
1158            }
1159        }
1160
1161        // Create an iterator that claims to have at most 5 elements but actually has 10.
1162        let lying_iter = LyingIterator {
1163            values: vec![
1164                true, false, true, false, true, false, true, false, true, false,
1165            ],
1166            index: 0,
1167        };
1168
1169        // Collect the iterator. This would cause UB in the old implementation
1170        // if it trusted the upper bound and used append_unchecked beyond capacity.
1171        let bit_buf: BitBufferMut = lying_iter.collect();
1172
1173        // Verify all 10 elements were collected correctly.
1174        assert_eq!(bit_buf.len(), 10);
1175        for i in 0..10 {
1176            assert_eq!(bit_buf.value(i), i % 2 == 0);
1177        }
1178    }
1179
1180    #[test]
1181    fn test_split_off() {
1182        // Test splitting at various positions and across a byte boundary
1183        for i in 0..10 {
1184            let buf = bitbuffer![0 1 0 1 0 1 0 1 0 1];
1185
1186            let mut buf_mut = buf.clone().into_mut();
1187            assert_eq!(buf_mut.len(), 10);
1188
1189            let tail = buf_mut.split_off(i);
1190            assert_eq!(buf_mut.len(), i);
1191            assert_eq!(buf_mut.freeze(), buf.slice(0..i));
1192
1193            assert_eq!(tail.len(), 10 - i);
1194            assert_eq!(tail.freeze(), buf.slice(i..10));
1195        }
1196    }
1197
1198    #[test]
1199    fn test_split_off_with_offset() {
1200        // Test splitting at various positions and across a byte boundary
1201        for i in 0..10 {
1202            let buf = bitbuffer![0 1 0 1 0 1 0 1 0 1 0 1].slice(2..);
1203
1204            let mut buf_mut = buf.clone().into_mut();
1205            assert_eq!(buf_mut.len(), 10);
1206
1207            let tail = buf_mut.split_off(i);
1208            assert_eq!(buf_mut.len(), i);
1209            assert_eq!(buf_mut.freeze(), buf.slice(0..i));
1210
1211            assert_eq!(tail.len(), 10 - i);
1212            assert_eq!(tail.freeze(), buf.slice(i..10));
1213        }
1214    }
1215}