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