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
576// allow building a buffer from a set of truthy byte values.
577impl From<&[u8]> for BitBufferMut {
578    fn from(value: &[u8]) -> Self {
579        BitBufferMut::collect_bool(value.len(), |i| value[i] > 0)
580    }
581}
582
583impl From<Vec<bool>> for BitBufferMut {
584    fn from(value: Vec<bool>) -> Self {
585        value.as_slice().into()
586    }
587}
588
589impl FromIterator<bool> for BitBufferMut {
590    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
591        let mut iter = iter.into_iter();
592
593        // Since we do not know the length of the iterator, we can only guess how much memory we
594        // need to reserve. Note that these hints may be inaccurate.
595        let (lower_bound, _) = iter.size_hint();
596
597        // We choose not to use the optional upper bound size hint to match the standard library.
598
599        // Initialize all bits to 0 with the given length. By doing this, we only need to set bits
600        // that are true (and this is faster from benchmarks).
601        let mut buf = BitBufferMut::new_unset(lower_bound);
602        assert_eq!(buf.offset, 0);
603
604        // Directly write within our known capacity.
605        let ptr = buf.buffer.as_mut_ptr();
606        for i in 0..lower_bound {
607            let Some(v) = iter.next() else {
608                // SAFETY: We are definitely under the capacity and all values are already
609                // initialized from `new_unset`.
610                unsafe { buf.set_len(i) };
611                return buf;
612            };
613
614            if v {
615                // SAFETY: We have ensured that we are within the capacity.
616                unsafe { set_bit_unchecked(ptr, i) }
617            }
618        }
619
620        // Append the remaining items (as we do not know how many more there are).
621        for v in iter {
622            buf.append(v);
623        }
624
625        buf
626    }
627}
628
629#[cfg(test)]
630mod tests {
631    use crate::BufferMut;
632    use crate::bit::buf_mut::BitBufferMut;
633    use crate::bitbuffer;
634    use crate::bitbuffer_mut;
635    use crate::buffer_mut;
636
637    #[test]
638    fn test_bits_mut() {
639        let mut bools = bitbuffer_mut![false; 10];
640        bools.set_to(0, true);
641        bools.set_to(9, true);
642
643        let bools = bools.freeze();
644        assert!(bools.value(0));
645        for i in 1..=8 {
646            assert!(!bools.value(i));
647        }
648        assert!(bools.value(9));
649    }
650
651    #[test]
652    fn test_append_n() {
653        let mut bools = BitBufferMut::with_capacity(10);
654        assert_eq!(bools.len(), 0);
655        assert!(bools.is_empty());
656
657        bools.append(true);
658        bools.append_n(false, 8);
659        bools.append_n(true, 1);
660
661        let bools = bools.freeze();
662
663        assert_eq!(bools.true_count(), 2);
664        assert!(bools.value(0));
665        assert!(bools.value(9));
666    }
667
668    #[test]
669    fn test_reserve_ensures_len_plus_additional() {
670        // This test documents the fix for the bug where reserve was incorrectly
671        // calculating additional bytes from capacity instead of len.
672
673        let mut bits = BitBufferMut::with_capacity(10);
674        assert_eq!(bits.len(), 0);
675
676        bits.reserve(100);
677
678        // Should have capacity for at least len + 100 = 0 + 100 = 100 bits.
679        assert!(bits.capacity() >= 100);
680
681        bits.append_n(true, 50);
682        assert_eq!(bits.len(), 50);
683
684        bits.reserve(100);
685
686        // Should have capacity for at least len + 100 = 50 + 100 = 150 bits.
687        assert!(bits.capacity() >= 150);
688    }
689
690    #[test]
691    fn test_with_offset_zero() {
692        // Test basic operations when offset is 0
693        let buf = BufferMut::zeroed(2);
694        let mut bit_buf = BitBufferMut::from_buffer(buf, 0, 16);
695
696        // Set some bits
697        bit_buf.set(0);
698        bit_buf.set(7);
699        bit_buf.set(8);
700        bit_buf.set(15);
701
702        // Verify values
703        assert!(bit_buf.value(0));
704        assert!(bit_buf.value(7));
705        assert!(bit_buf.value(8));
706        assert!(bit_buf.value(15));
707        assert!(!bit_buf.value(1));
708        assert!(!bit_buf.value(9));
709
710        // Verify underlying bytes
711        assert_eq!(bit_buf.as_slice()[0], 0b10000001);
712        assert_eq!(bit_buf.as_slice()[1], 0b10000001);
713    }
714
715    #[test]
716    fn test_with_offset_within_byte() {
717        // Test operations with offset=3 (within first byte)
718        let buf = buffer_mut![0b11111111, 0b00000000, 0b00000000];
719        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 10);
720
721        // Initially, bits 3-7 from first byte are set (5 bits)
722        // and bits 0-4 from second byte are unset (5 bits more)
723        assert!(bit_buf.value(0)); // bit 3 of byte 0
724        assert!(bit_buf.value(4)); // bit 7 of byte 0
725        assert!(!bit_buf.value(5)); // bit 0 of byte 1
726
727        // Set a bit in the second byte's range
728        bit_buf.set(7);
729        assert!(bit_buf.value(7));
730
731        // Unset a bit in the first byte's range
732        bit_buf.unset(0);
733        assert!(!bit_buf.value(0));
734    }
735
736    #[test]
737    fn test_with_offset_byte_boundary() {
738        // Test operations with offset=8 (exactly one byte)
739        let buf = buffer_mut![0xFF, 0x00, 0xFF];
740        let mut bit_buf = BitBufferMut::from_buffer(buf, 8, 16);
741
742        // Buffer starts at byte 1, so all bits should be unset initially
743        for i in 0..8 {
744            assert!(!bit_buf.value(i));
745        }
746        // Next byte has all bits set
747        for i in 8..16 {
748            assert!(bit_buf.value(i));
749        }
750
751        // Set some bits
752        bit_buf.set(0);
753        bit_buf.set(3);
754        assert!(bit_buf.value(0));
755        assert!(bit_buf.value(3));
756    }
757
758    #[test]
759    fn test_with_large_offset() {
760        // Test with offset=13 (one byte + 5 bits)
761        let buf = buffer_mut![0xFF, 0xFF, 0xFF, 0xFF];
762        let mut bit_buf = BitBufferMut::from_buffer(buf, 13, 10);
763
764        // All bits should initially be set
765        for i in 0..10 {
766            assert!(bit_buf.value(i));
767        }
768
769        // Unset some bits
770        bit_buf.unset(0);
771        bit_buf.unset(5);
772        bit_buf.unset(9);
773
774        assert!(!bit_buf.value(0));
775        assert!(bit_buf.value(1));
776        assert!(!bit_buf.value(5));
777        assert!(!bit_buf.value(9));
778    }
779
780    #[test]
781    fn test_append_with_offset() {
782        // Create buffer with offset
783        let buf = buffer_mut![0b11100000]; // First 3 bits unset, last 5 set
784        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0); // Start at bit 3, len=0
785
786        // Append some bits
787        bit_buf.append(false); // Should use bit 3
788        bit_buf.append(true); // Should use bit 4
789        bit_buf.append(true); // Should use bit 5
790
791        assert_eq!(bit_buf.len(), 3);
792        assert!(!bit_buf.value(0));
793        assert!(bit_buf.value(1));
794        assert!(bit_buf.value(2));
795    }
796
797    #[test]
798    fn test_append_n_with_offset_crossing_boundary() {
799        // Create buffer with offset that will cross byte boundary when appending
800        let buf = BufferMut::zeroed(4);
801        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
802
803        // Append enough bits to cross into next byte
804        bit_buf.append_n(true, 10); // 5 bits left in first byte, then 5 in second
805
806        assert_eq!(bit_buf.len(), 10);
807        for i in 0..10 {
808            assert!(bit_buf.value(i));
809        }
810
811        // Verify the underlying bytes
812        // Bits 5-7 of byte 0 should be set (3 bits)
813        // Bits 0-6 of byte 1 should be set (7 bits)
814        assert_eq!(bit_buf.as_slice()[0], 0b11100000);
815        assert_eq!(bit_buf.as_slice()[1], 0b01111111);
816    }
817
818    #[test]
819    fn test_truncate_with_offset() {
820        let buf = buffer_mut![0xFF, 0xFF];
821        let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 12);
822
823        assert_eq!(bit_buf.len(), 12);
824
825        // Truncate to 8 bits
826        bit_buf.truncate(8);
827        assert_eq!(bit_buf.len(), 8);
828
829        // Truncate to 3 bits
830        bit_buf.truncate(3);
831        assert_eq!(bit_buf.len(), 3);
832
833        // Truncating to larger length should be no-op
834        bit_buf.truncate(10);
835        assert_eq!(bit_buf.len(), 3);
836    }
837
838    #[test]
839    fn test_capacity_with_offset() {
840        // Use exact buffer size to test capacity calculation
841        let buf = buffer_mut![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // Exactly 10 bytes = 80 bits
842        let bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
843
844        // Capacity should be at least buffer length minus offset
845        // (may be more due to allocator rounding)
846        assert!(bit_buf.capacity() >= 75);
847        // And should account for offset
848        assert_eq!(bit_buf.capacity() % 8, (80 - 5) % 8);
849    }
850
851    #[test]
852    fn test_reserve_with_offset() {
853        // Use exact buffer to test reserve
854        let buf = buffer_mut![0, 0]; // Exactly 2 bytes = 16 bits
855        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
856
857        // Current capacity should be at least 13 bits (16 - 3)
858        let initial_capacity = bit_buf.capacity();
859        assert!(initial_capacity >= 13);
860
861        // Reserve 20 more bits (need total of offset 3 + len 0 + additional 20 = 23 bits)
862        bit_buf.reserve(20);
863
864        // Should now have at least 20 bits of capacity
865        assert!(bit_buf.capacity() >= 20);
866    }
867
868    #[test]
869    fn test_freeze_with_offset() {
870        let buf = buffer_mut![0b11110000, 0b00001111];
871        let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
872
873        // Set some bits
874        bit_buf.set(0);
875        bit_buf.set(7);
876
877        // Freeze and verify offset is preserved
878        let frozen = bit_buf.freeze();
879        assert_eq!(frozen.offset(), 4);
880        assert_eq!(frozen.len(), 8);
881
882        // Verify values through frozen buffer
883        assert!(frozen.value(0));
884        assert!(frozen.value(7));
885    }
886
887    #[cfg_attr(miri, ignore)] // bitvec crate uses a ptr cast that Miri doesn't support
888    #[test]
889    fn test_append_buffer_with_offsets() {
890        // Create source buffer with offset
891        let source = bitbuffer![false, false, true, true, false, true];
892
893        // Create destination buffer with offset
894        let buf = BufferMut::zeroed(4);
895        let mut dest = BitBufferMut::from_buffer(buf, 3, 0);
896
897        // Append 2 initial bits
898        dest.append(true);
899        dest.append(false);
900
901        // Append the source buffer
902        dest.append_buffer(&source);
903
904        assert_eq!(dest.len(), 8);
905        assert!(dest.value(0)); // Our first append
906        assert!(!dest.value(1)); // Our second append
907        assert!(!dest.value(2)); // From source[0]
908        assert!(!dest.value(3)); // From source[1]
909        assert!(dest.value(4)); // From source[2]
910        assert!(dest.value(5)); // From source[3]
911        assert!(!dest.value(6)); // From source[4]
912        assert!(dest.value(7)); // From source[5]
913    }
914
915    #[test]
916    fn test_set_unset_unchecked_with_offset() {
917        let buf = BufferMut::zeroed(3);
918        let mut bit_buf = BitBufferMut::from_buffer(buf, 7, 10);
919
920        unsafe {
921            bit_buf.set_unchecked(0);
922            bit_buf.set_unchecked(5);
923            bit_buf.set_unchecked(9);
924        }
925
926        assert!(bit_buf.value(0));
927        assert!(bit_buf.value(5));
928        assert!(bit_buf.value(9));
929
930        unsafe {
931            bit_buf.unset_unchecked(5);
932        }
933
934        assert!(!bit_buf.value(5));
935    }
936
937    #[test]
938    fn test_value_unchecked_with_offset() {
939        let buf = buffer_mut![0b11110000, 0b00001111];
940        let bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
941
942        unsafe {
943            // First 4 bits of logical buffer come from bits 4-7 of first byte (all 1s)
944            assert!(bit_buf.value_unchecked(0));
945            assert!(bit_buf.value_unchecked(3));
946
947            // Next 4 bits come from bits 0-3 of second byte (all 1s)
948            assert!(bit_buf.value_unchecked(4));
949            assert!(bit_buf.value_unchecked(7));
950        }
951    }
952
953    #[test]
954    fn test_append_alternating_with_offset() {
955        let buf = BufferMut::zeroed(4);
956        let mut bit_buf = BitBufferMut::from_buffer(buf, 2, 0);
957
958        // Append alternating pattern across byte boundaries
959        for i in 0..20 {
960            bit_buf.append(i % 2 == 0);
961        }
962
963        assert_eq!(bit_buf.len(), 20);
964        for i in 0..20 {
965            assert_eq!(bit_buf.value(i), i % 2 == 0);
966        }
967    }
968
969    #[test]
970    fn test_new_set_new_unset() {
971        let set_buf = bitbuffer_mut![true; 10];
972        let unset_buf = bitbuffer_mut![false; 10];
973
974        for i in 0..10 {
975            assert!(set_buf.value(i));
976            assert!(!unset_buf.value(i));
977        }
978
979        assert_eq!(set_buf.len(), 10);
980        assert_eq!(unset_buf.len(), 10);
981    }
982
983    #[test]
984    fn test_append_n_false_with_offset() {
985        let buf = BufferMut::zeroed(4);
986        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
987
988        bit_buf.append_n(false, 15);
989
990        assert_eq!(bit_buf.len(), 15);
991        for i in 0..15 {
992            assert!(!bit_buf.value(i));
993        }
994    }
995
996    #[test]
997    fn test_append_n_true_with_offset() {
998        let buf = BufferMut::zeroed(4);
999        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1000
1001        bit_buf.append_n(true, 15);
1002
1003        assert_eq!(bit_buf.len(), 15);
1004        for i in 0..15 {
1005            assert!(bit_buf.value(i));
1006        }
1007    }
1008
1009    #[test]
1010    fn test_mixed_operations_with_offset() {
1011        // Complex test combining multiple operations with offset
1012        let buf = BufferMut::zeroed(5);
1013        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
1014
1015        // Append some bits
1016        bit_buf.append_n(true, 5);
1017        bit_buf.append_n(false, 3);
1018        bit_buf.append(true);
1019
1020        assert_eq!(bit_buf.len(), 9);
1021
1022        // Set and unset
1023        bit_buf.set(6); // Was false, now true
1024        bit_buf.unset(2); // Was true, now false
1025
1026        // Verify
1027        assert!(bit_buf.value(0));
1028        assert!(bit_buf.value(1));
1029        assert!(!bit_buf.value(2)); // Unset
1030        assert!(bit_buf.value(3));
1031        assert!(bit_buf.value(4));
1032        assert!(!bit_buf.value(5));
1033        assert!(bit_buf.value(6)); // Set
1034        assert!(!bit_buf.value(7));
1035        assert!(bit_buf.value(8));
1036
1037        // Truncate
1038        bit_buf.truncate(6);
1039        assert_eq!(bit_buf.len(), 6);
1040
1041        // Freeze and verify offset preserved
1042        let frozen = bit_buf.freeze();
1043        assert_eq!(frozen.offset(), 3);
1044        assert_eq!(frozen.len(), 6);
1045    }
1046
1047    #[test]
1048    fn test_from_iterator_with_incorrect_size_hint() {
1049        // This test catches a bug where FromIterator assumed the upper bound
1050        // from size_hint was accurate. The iterator contract allows the actual
1051        // count to exceed the upper bound, which could cause UB if we used
1052        // append_unchecked beyond the allocated capacity.
1053
1054        // Custom iterator that lies about its size hint.
1055        struct LyingIterator {
1056            values: Vec<bool>,
1057            index: usize,
1058        }
1059
1060        impl Iterator for LyingIterator {
1061            type Item = bool;
1062
1063            fn next(&mut self) -> Option<Self::Item> {
1064                (self.index < self.values.len()).then(|| {
1065                    let val = self.values[self.index];
1066                    self.index += 1;
1067                    val
1068                })
1069            }
1070
1071            fn size_hint(&self) -> (usize, Option<usize>) {
1072                // Deliberately return an incorrect upper bound that's smaller
1073                // than the actual number of elements we'll yield.
1074                let remaining = self.values.len() - self.index;
1075                let lower = remaining.min(5); // Correct lower bound (but capped).
1076                let upper = Some(5); // Incorrect upper bound - we actually have more!
1077                (lower, upper)
1078            }
1079        }
1080
1081        // Create an iterator that claims to have at most 5 elements but actually has 10.
1082        let lying_iter = LyingIterator {
1083            values: vec![
1084                true, false, true, false, true, false, true, false, true, false,
1085            ],
1086            index: 0,
1087        };
1088
1089        // Collect the iterator. This would cause UB in the old implementation
1090        // if it trusted the upper bound and used append_unchecked beyond capacity.
1091        let bit_buf: BitBufferMut = lying_iter.collect();
1092
1093        // Verify all 10 elements were collected correctly.
1094        assert_eq!(bit_buf.len(), 10);
1095        for i in 0..10 {
1096            assert_eq!(bit_buf.value(i), i % 2 == 0);
1097        }
1098    }
1099}