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