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