Skip to main content

vortex_buffer/bit/
buf_mut.rs

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