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