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