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