vortex_buffer/bit/
buf_mut.rs

1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright the Vortex contributors
3
4use bitvec::view::BitView;
5
6use crate::bit::{get_bit_unchecked, set_bit_unchecked, unset_bit_unchecked};
7use crate::{BitBuffer, BufferMut, ByteBufferMut, buffer_mut};
8
9/// A mutable bitset buffer that allows random access to individual bits for set and get.
10///
11///
12/// # Example
13/// ```
14/// use vortex_buffer::BitBufferMut;
15///
16/// let mut bools = BitBufferMut::new_unset(10);
17/// bools.set_to(9, true);
18/// for i in 0..9 {
19///    assert!(!bools.value(i));
20/// }
21/// assert!(bools.value(9));
22///
23/// // Freeze into a new bools vector.
24/// let bools = bools.freeze();
25/// ```
26///
27/// See also: [`BitBuffer`].
28pub struct BitBufferMut {
29    buffer: ByteBufferMut,
30    offset: usize,
31    len: usize,
32}
33
34impl BitBufferMut {
35    /// Create new bit buffer from given byte buffer and logical bit length
36    pub fn from_buffer(buffer: ByteBufferMut, offset: usize, len: usize) -> Self {
37        assert!(
38            len <= buffer.len() * 8,
39            "Buffer len {} is too short for the given length {len}",
40            buffer.len()
41        );
42        Self {
43            buffer,
44            offset,
45            len,
46        }
47    }
48
49    /// Create a new empty mutable bit buffer with requested capacity (in bits).
50    pub fn with_capacity(capacity: usize) -> Self {
51        Self {
52            buffer: BufferMut::with_capacity(capacity.div_ceil(8)),
53            offset: 0,
54            len: 0,
55        }
56    }
57
58    /// Create a new mutable buffer with requested `len` and all bits set to `true`.
59    pub fn new_set(len: usize) -> Self {
60        Self {
61            buffer: buffer_mut![0xFF; len.div_ceil(8)],
62            offset: 0,
63            len,
64        }
65    }
66
67    /// Create a new mutable buffer with requested `len` and all bits set to `false`.
68    pub fn new_unset(len: usize) -> Self {
69        Self {
70            buffer: BufferMut::zeroed(len.div_ceil(8)),
71            offset: 0,
72            len,
73        }
74    }
75
76    /// Create a new empty `BitBufferMut`.
77    #[inline(always)]
78    pub fn empty() -> Self {
79        Self::with_capacity(0)
80    }
81
82    /// Create a new mutable buffer with requested `len` and all bits set to `value`.
83    pub fn full(value: bool, len: usize) -> Self {
84        if value {
85            Self::new_set(len)
86        } else {
87            Self::new_unset(len)
88        }
89    }
90
91    /// Get the current populated length of the buffer.
92    #[inline(always)]
93    pub fn len(&self) -> usize {
94        self.len
95    }
96
97    /// True if the buffer has length 0.
98    #[inline(always)]
99    pub fn is_empty(&self) -> bool {
100        self.len == 0
101    }
102
103    /// Get the value at the requested index.
104    #[inline(always)]
105    pub fn value(&self, index: usize) -> bool {
106        assert!(index < self.len);
107        // SAFETY: checked by assertion
108        unsafe { self.value_unchecked(index) }
109    }
110
111    /// Get the value at the requested index without bounds checking.
112    ///
113    /// # Safety
114    ///
115    /// The caller must ensure that `index` is less than the length of the buffer.
116    #[inline(always)]
117    pub unsafe fn value_unchecked(&self, index: usize) -> bool {
118        unsafe { get_bit_unchecked(self.buffer.as_ptr(), self.offset + index) }
119    }
120
121    /// Get the bit capacity of the buffer.
122    #[inline(always)]
123    pub fn capacity(&self) -> usize {
124        (self.buffer.capacity() * 8) - self.offset
125    }
126
127    /// Reserve additional bit capacity for the buffer.
128    pub fn reserve(&mut self, additional: usize) {
129        let required_capacity = (self.offset + self.len + additional).div_ceil(8);
130        let buffer_capacity = self.buffer.capacity();
131        if required_capacity > self.buffer.capacity() {
132            let additional = required_capacity - buffer_capacity;
133            self.buffer.reserve(additional);
134        }
135    }
136
137    /// Set the bit at `index` to the given boolean value.
138    ///
139    /// This operation is checked so if `index` exceeds the buffer length, this will panic.
140    pub fn set_to(&mut self, index: usize, value: bool) {
141        if value {
142            self.set(index);
143        } else {
144            self.unset(index);
145        }
146    }
147
148    /// Set the bit at `index` to the given boolean value without checking bounds.
149    ///
150    /// # Safety
151    ///
152    /// The caller must ensure that `index` does not exceed the largest bit index in the backing buffer.
153    pub unsafe fn set_to_unchecked(&mut self, index: usize, value: bool) {
154        if value {
155            // SAFETY: checked by caller
156            unsafe { self.set_unchecked(index) }
157        } else {
158            // SAFETY: checked by caller
159            unsafe { self.unset_unchecked(index) }
160        }
161    }
162
163    /// Set a position to `true`.
164    ///
165    /// This operation is checked so if `index` exceeds the buffer length, this will panic.
166    pub fn set(&mut self, index: usize) {
167        assert!(index < self.len, "index {index} exceeds len {}", self.len);
168
169        // SAFETY: checked by assertion
170        unsafe { self.set_unchecked(index) };
171    }
172
173    /// Set a position to `false`.
174    ///
175    /// This operation is checked so if `index` exceeds the buffer length, this will panic.
176    pub fn unset(&mut self, index: usize) {
177        assert!(index < self.len, "index {index} exceeds len {}", self.len);
178
179        // SAFETY: checked by assertion
180        unsafe { self.unset_unchecked(index) };
181    }
182
183    /// Set the bit at `index` to `true` without checking bounds.
184    ///
185    /// # Safety
186    ///
187    /// The caller must ensure that `index` does not exceed the largest bit index in the backing buffer.
188    pub unsafe fn set_unchecked(&mut self, index: usize) {
189        // SAFETY: checked by caller
190        unsafe { set_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
191    }
192
193    /// Unset the bit at `index` without checking bounds.
194    ///
195    /// # Safety
196    ///
197    /// The caller must ensure that `index` does not exceed the largest bit index in the backing buffer.
198    pub unsafe fn unset_unchecked(&mut self, index: usize) {
199        // SAFETY: checked by caller
200        unsafe { unset_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
201    }
202
203    /// Truncate the buffer to the given length.
204    pub fn truncate(&mut self, len: usize) {
205        if len > self.len {
206            return;
207        }
208
209        let new_len_bytes = (self.offset + len).div_ceil(8);
210        self.buffer.truncate(new_len_bytes);
211        self.len = len;
212    }
213
214    /// Append a new boolean into the bit buffer, incrementing the length.
215    pub fn append(&mut self, value: bool) {
216        if value {
217            self.append_true()
218        } else {
219            self.append_false()
220        }
221    }
222
223    /// Append a new true value to the buffer.
224    pub fn append_true(&mut self) {
225        let bit_pos = self.offset + self.len;
226        let byte_pos = bit_pos / 8;
227        let bit_in_byte = bit_pos % 8;
228
229        // Ensure buffer has enough bytes
230        if byte_pos >= self.buffer.len() {
231            self.buffer.push(0u8);
232        }
233
234        // Set the bit
235        self.buffer.as_mut_slice()[byte_pos] |= 1 << bit_in_byte;
236        self.len += 1;
237    }
238
239    /// Append a new false value to the buffer.
240    pub fn append_false(&mut self) {
241        let bit_pos = self.offset + self.len;
242        let byte_pos = bit_pos / 8;
243        let bit_in_byte = bit_pos % 8;
244
245        // Ensure buffer has enough bytes
246        if byte_pos >= self.buffer.len() {
247            self.buffer.push(0u8);
248        }
249
250        // Bit is already 0 if we just pushed a new byte, otherwise ensure it's unset
251        if bit_in_byte != 0 {
252            self.buffer.as_mut_slice()[byte_pos] &= !(1 << bit_in_byte);
253        }
254
255        self.len += 1;
256    }
257
258    /// Append several boolean values into the bit buffer. After this operation,
259    /// the length will be incremented by `n`.
260    ///
261    /// Panics if the buffer does not have `n` slots left.
262    pub fn append_n(&mut self, value: bool, n: usize) {
263        if n == 0 {
264            return;
265        }
266
267        let start_bit_pos = self.offset + self.len;
268        let end_bit_pos = start_bit_pos + n;
269        let required_bytes = end_bit_pos.div_ceil(8);
270
271        // Ensure buffer has enough bytes
272        if required_bytes > self.buffer.len() {
273            self.buffer.push_n(0x00, required_bytes - self.buffer.len());
274        }
275
276        let fill_byte = if value { 0xFF } else { 0x00 };
277
278        // Calculate byte positions
279        let start_byte = start_bit_pos / 8;
280        let start_bit = start_bit_pos % 8;
281        let end_byte = end_bit_pos / 8;
282        let end_bit = end_bit_pos % 8;
283
284        let slice = self.buffer.as_mut_slice();
285
286        if start_byte == end_byte {
287            // All bits are in the same byte
288            let mask = ((1u8 << (end_bit - start_bit)) - 1) << start_bit;
289            if value {
290                slice[start_byte] |= mask;
291            } else {
292                slice[start_byte] &= !mask;
293            }
294        } else {
295            // Fill the first partial byte
296            if start_bit != 0 {
297                let mask = !((1u8 << start_bit) - 1);
298                if value {
299                    slice[start_byte] |= mask;
300                } else {
301                    slice[start_byte] &= !mask;
302                }
303            }
304
305            // Fill the complete middle bytes
306            let fill_start = if start_bit != 0 {
307                start_byte + 1
308            } else {
309                start_byte
310            };
311            let fill_end = end_byte;
312            if fill_start < fill_end {
313                slice[fill_start..fill_end].fill(fill_byte);
314            }
315
316            // Fill the last partial byte
317            if end_bit != 0 {
318                let mask = (1u8 << end_bit) - 1;
319                if value {
320                    slice[end_byte] |= mask;
321                } else {
322                    slice[end_byte] &= !mask;
323                }
324            }
325        }
326
327        self.len += n;
328    }
329
330    /// Append a [`BitBuffer`] to this [`BitBufferMut`]
331    ///
332    /// This efficiently copies all bits from the source buffer to the end of this buffer.
333    pub fn append_buffer(&mut self, buffer: &BitBuffer) {
334        let bit_len = buffer.len();
335        if bit_len == 0 {
336            return;
337        }
338
339        let start_bit_pos = self.offset + self.len;
340        let end_bit_pos = start_bit_pos + bit_len;
341        let required_bytes = end_bit_pos.div_ceil(8);
342
343        // Ensure buffer has enough bytes
344        if required_bytes > self.buffer.len() {
345            self.buffer.push_n(0x00, required_bytes - self.buffer.len());
346        }
347
348        // Use bitvec for efficient bit copying
349        let self_slice = self
350            .buffer
351            .as_mut_slice()
352            .view_bits_mut::<bitvec::prelude::Lsb0>();
353        let other_slice = buffer
354            .inner()
355            .as_slice()
356            .view_bits::<bitvec::prelude::Lsb0>();
357
358        // Copy from source buffer (accounting for its offset) to destination (accounting for our offset + len)
359        let source_range = buffer.offset()..buffer.offset() + bit_len;
360        self_slice[start_bit_pos..end_bit_pos].copy_from_bitslice(&other_slice[source_range]);
361
362        self.len += bit_len;
363    }
364
365    /// Freeze the buffer in its current state into an immutable `BoolBuffer`.
366    pub fn freeze(self) -> BitBuffer {
367        BitBuffer::new_with_offset(self.buffer.freeze(), self.len, self.offset)
368    }
369
370    /// Get the underlying bytes as a slice
371    pub fn as_slice(&self) -> &[u8] {
372        self.buffer.as_slice()
373    }
374
375    /// Get the underlying bytes as a mutable slice
376    pub fn as_mut_slice(&mut self) -> &mut [u8] {
377        self.buffer.as_mut_slice()
378    }
379}
380
381impl Default for BitBufferMut {
382    fn default() -> Self {
383        Self::with_capacity(0)
384    }
385}
386
387impl From<&[bool]> for BitBufferMut {
388    fn from(value: &[bool]) -> Self {
389        let mut buf = BitBufferMut::new_unset(value.len());
390        for (i, &v) in value.iter().enumerate() {
391            if v {
392                // SAFETY: i is in bounds
393                unsafe { buf.set_unchecked(i) }
394            }
395        }
396        buf
397    }
398}
399
400impl From<Vec<bool>> for BitBufferMut {
401    fn from(value: Vec<bool>) -> Self {
402        value.as_slice().into()
403    }
404}
405
406impl FromIterator<bool> for BitBufferMut {
407    fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
408        let iter = iter.into_iter();
409        let (low, high) = iter.size_hint();
410        if let Some(len) = high {
411            let mut buf = BitBufferMut::new_unset(len);
412            for (i, v) in iter.enumerate() {
413                if v {
414                    // SAFETY: i is in bounds
415                    unsafe { buf.set_unchecked(i) }
416                }
417            }
418            buf
419        } else {
420            let mut buf = BitBufferMut::with_capacity(low);
421            for v in iter {
422                buf.append(v);
423            }
424            buf
425        }
426    }
427}
428
429#[cfg(test)]
430mod tests {
431    use crate::bit::buf_mut::BitBufferMut;
432    use crate::{BufferMut, bitbuffer, bitbuffer_mut, buffer_mut};
433
434    #[test]
435    fn test_bits_mut() {
436        let mut bools = bitbuffer_mut![false; 10];
437        bools.set_to(0, true);
438        bools.set_to(9, true);
439
440        let bools = bools.freeze();
441        assert!(bools.value(0));
442        for i in 1..=8 {
443            assert!(!bools.value(i));
444        }
445        assert!(bools.value(9));
446    }
447
448    #[test]
449    fn test_append_n() {
450        let mut bools = BitBufferMut::with_capacity(10);
451        assert_eq!(bools.len(), 0);
452        assert!(bools.is_empty());
453
454        bools.append(true);
455        bools.append_n(false, 8);
456        bools.append_n(true, 1);
457
458        let bools = bools.freeze();
459
460        assert_eq!(bools.true_count(), 2);
461        assert!(bools.value(0));
462        assert!(bools.value(9));
463    }
464
465    #[test]
466    fn test_with_offset_zero() {
467        // Test basic operations when offset is 0
468        let buf = BufferMut::zeroed(2);
469        let mut bit_buf = BitBufferMut::from_buffer(buf, 0, 16);
470
471        // Set some bits
472        bit_buf.set(0);
473        bit_buf.set(7);
474        bit_buf.set(8);
475        bit_buf.set(15);
476
477        // Verify values
478        assert!(bit_buf.value(0));
479        assert!(bit_buf.value(7));
480        assert!(bit_buf.value(8));
481        assert!(bit_buf.value(15));
482        assert!(!bit_buf.value(1));
483        assert!(!bit_buf.value(9));
484
485        // Verify underlying bytes
486        assert_eq!(bit_buf.as_slice()[0], 0b10000001);
487        assert_eq!(bit_buf.as_slice()[1], 0b10000001);
488    }
489
490    #[test]
491    fn test_with_offset_within_byte() {
492        // Test operations with offset=3 (within first byte)
493        let buf = buffer_mut![0b11111111, 0b00000000, 0b00000000];
494        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 10);
495
496        // Initially, bits 3-7 from first byte are set (5 bits)
497        // and bits 0-4 from second byte are unset (5 bits more)
498        assert!(bit_buf.value(0)); // bit 3 of byte 0
499        assert!(bit_buf.value(4)); // bit 7 of byte 0
500        assert!(!bit_buf.value(5)); // bit 0 of byte 1
501
502        // Set a bit in the second byte's range
503        bit_buf.set(7);
504        assert!(bit_buf.value(7));
505
506        // Unset a bit in the first byte's range
507        bit_buf.unset(0);
508        assert!(!bit_buf.value(0));
509    }
510
511    #[test]
512    fn test_with_offset_byte_boundary() {
513        // Test operations with offset=8 (exactly one byte)
514        let buf = buffer_mut![0xFF, 0x00, 0xFF];
515        let mut bit_buf = BitBufferMut::from_buffer(buf, 8, 16);
516
517        // Buffer starts at byte 1, so all bits should be unset initially
518        for i in 0..8 {
519            assert!(!bit_buf.value(i));
520        }
521        // Next byte has all bits set
522        for i in 8..16 {
523            assert!(bit_buf.value(i));
524        }
525
526        // Set some bits
527        bit_buf.set(0);
528        bit_buf.set(3);
529        assert!(bit_buf.value(0));
530        assert!(bit_buf.value(3));
531    }
532
533    #[test]
534    fn test_with_large_offset() {
535        // Test with offset=13 (one byte + 5 bits)
536        let buf = buffer_mut![0xFF, 0xFF, 0xFF, 0xFF];
537        let mut bit_buf = BitBufferMut::from_buffer(buf, 13, 10);
538
539        // All bits should initially be set
540        for i in 0..10 {
541            assert!(bit_buf.value(i));
542        }
543
544        // Unset some bits
545        bit_buf.unset(0);
546        bit_buf.unset(5);
547        bit_buf.unset(9);
548
549        assert!(!bit_buf.value(0));
550        assert!(bit_buf.value(1));
551        assert!(!bit_buf.value(5));
552        assert!(!bit_buf.value(9));
553    }
554
555    #[test]
556    fn test_append_with_offset() {
557        // Create buffer with offset
558        let buf = buffer_mut![0b11100000]; // First 3 bits unset, last 5 set
559        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0); // Start at bit 3, len=0
560
561        // Append some bits
562        bit_buf.append(false); // Should use bit 3
563        bit_buf.append(true); // Should use bit 4
564        bit_buf.append(true); // Should use bit 5
565
566        assert_eq!(bit_buf.len(), 3);
567        assert!(!bit_buf.value(0));
568        assert!(bit_buf.value(1));
569        assert!(bit_buf.value(2));
570    }
571
572    #[test]
573    fn test_append_n_with_offset_crossing_boundary() {
574        // Create buffer with offset that will cross byte boundary when appending
575        let buf = BufferMut::zeroed(4);
576        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
577
578        // Append enough bits to cross into next byte
579        bit_buf.append_n(true, 10); // 5 bits left in first byte, then 5 in second
580
581        assert_eq!(bit_buf.len(), 10);
582        for i in 0..10 {
583            assert!(bit_buf.value(i));
584        }
585
586        // Verify the underlying bytes
587        // Bits 5-7 of byte 0 should be set (3 bits)
588        // Bits 0-6 of byte 1 should be set (7 bits)
589        assert_eq!(bit_buf.as_slice()[0], 0b11100000);
590        assert_eq!(bit_buf.as_slice()[1], 0b01111111);
591    }
592
593    #[test]
594    fn test_truncate_with_offset() {
595        let buf = buffer_mut![0xFF, 0xFF];
596        let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 12);
597
598        assert_eq!(bit_buf.len(), 12);
599
600        // Truncate to 8 bits
601        bit_buf.truncate(8);
602        assert_eq!(bit_buf.len(), 8);
603
604        // Truncate to 3 bits
605        bit_buf.truncate(3);
606        assert_eq!(bit_buf.len(), 3);
607
608        // Truncating to larger length should be no-op
609        bit_buf.truncate(10);
610        assert_eq!(bit_buf.len(), 3);
611    }
612
613    #[test]
614    fn test_capacity_with_offset() {
615        // Use exact buffer size to test capacity calculation
616        let buf = buffer_mut![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // Exactly 10 bytes = 80 bits
617        let bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
618
619        // Capacity should be at least buffer length minus offset
620        // (may be more due to allocator rounding)
621        assert!(bit_buf.capacity() >= 75);
622        // And should account for offset
623        assert_eq!(bit_buf.capacity() % 8, (80 - 5) % 8);
624    }
625
626    #[test]
627    fn test_reserve_with_offset() {
628        // Use exact buffer to test reserve
629        let buf = buffer_mut![0, 0]; // Exactly 2 bytes = 16 bits
630        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
631
632        // Current capacity should be at least 13 bits (16 - 3)
633        let initial_capacity = bit_buf.capacity();
634        assert!(initial_capacity >= 13);
635
636        // Reserve 20 more bits (need total of offset 3 + len 0 + additional 20 = 23 bits)
637        bit_buf.reserve(20);
638
639        // Should now have at least 20 bits of capacity
640        assert!(bit_buf.capacity() >= 20);
641    }
642
643    #[test]
644    fn test_freeze_with_offset() {
645        let buf = buffer_mut![0b11110000, 0b00001111];
646        let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
647
648        // Set some bits
649        bit_buf.set(0);
650        bit_buf.set(7);
651
652        // Freeze and verify offset is preserved
653        let frozen = bit_buf.freeze();
654        assert_eq!(frozen.offset(), 4);
655        assert_eq!(frozen.len(), 8);
656
657        // Verify values through frozen buffer
658        assert!(frozen.value(0));
659        assert!(frozen.value(7));
660    }
661
662    #[cfg_attr(miri, ignore)] // bitvec crate uses a ptr cast that Miri doesn't support
663    #[test]
664    fn test_append_buffer_with_offsets() {
665        // Create source buffer with offset
666        let source = bitbuffer![false, false, true, true, false, true];
667
668        // Create destination buffer with offset
669        let buf = BufferMut::zeroed(4);
670        let mut dest = BitBufferMut::from_buffer(buf, 3, 0);
671
672        // Append 2 initial bits
673        dest.append(true);
674        dest.append(false);
675
676        // Append the source buffer
677        dest.append_buffer(&source);
678
679        assert_eq!(dest.len(), 8);
680        assert!(dest.value(0)); // Our first append
681        assert!(!dest.value(1)); // Our second append
682        assert!(!dest.value(2)); // From source[0]
683        assert!(!dest.value(3)); // From source[1]
684        assert!(dest.value(4)); // From source[2]
685        assert!(dest.value(5)); // From source[3]
686        assert!(!dest.value(6)); // From source[4]
687        assert!(dest.value(7)); // From source[5]
688    }
689
690    #[test]
691    fn test_set_unset_unchecked_with_offset() {
692        let buf = BufferMut::zeroed(3);
693        let mut bit_buf = BitBufferMut::from_buffer(buf, 7, 10);
694
695        unsafe {
696            bit_buf.set_unchecked(0);
697            bit_buf.set_unchecked(5);
698            bit_buf.set_unchecked(9);
699        }
700
701        assert!(bit_buf.value(0));
702        assert!(bit_buf.value(5));
703        assert!(bit_buf.value(9));
704
705        unsafe {
706            bit_buf.unset_unchecked(5);
707        }
708
709        assert!(!bit_buf.value(5));
710    }
711
712    #[test]
713    fn test_value_unchecked_with_offset() {
714        let buf = buffer_mut![0b11110000, 0b00001111];
715        let bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
716
717        unsafe {
718            // First 4 bits of logical buffer come from bits 4-7 of first byte (all 1s)
719            assert!(bit_buf.value_unchecked(0));
720            assert!(bit_buf.value_unchecked(3));
721
722            // Next 4 bits come from bits 0-3 of second byte (all 1s)
723            assert!(bit_buf.value_unchecked(4));
724            assert!(bit_buf.value_unchecked(7));
725        }
726    }
727
728    #[test]
729    fn test_append_alternating_with_offset() {
730        let buf = BufferMut::zeroed(4);
731        let mut bit_buf = BitBufferMut::from_buffer(buf, 2, 0);
732
733        // Append alternating pattern across byte boundaries
734        for i in 0..20 {
735            bit_buf.append(i % 2 == 0);
736        }
737
738        assert_eq!(bit_buf.len(), 20);
739        for i in 0..20 {
740            assert_eq!(bit_buf.value(i), i % 2 == 0);
741        }
742    }
743
744    #[test]
745    fn test_new_set_new_unset() {
746        let set_buf = bitbuffer_mut![true; 10];
747        let unset_buf = bitbuffer_mut![false; 10];
748
749        for i in 0..10 {
750            assert!(set_buf.value(i));
751            assert!(!unset_buf.value(i));
752        }
753
754        assert_eq!(set_buf.len(), 10);
755        assert_eq!(unset_buf.len(), 10);
756    }
757
758    #[test]
759    fn test_append_n_false_with_offset() {
760        let buf = BufferMut::zeroed(4);
761        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
762
763        bit_buf.append_n(false, 15);
764
765        assert_eq!(bit_buf.len(), 15);
766        for i in 0..15 {
767            assert!(!bit_buf.value(i));
768        }
769    }
770
771    #[test]
772    fn test_append_n_true_with_offset() {
773        let buf = BufferMut::zeroed(4);
774        let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
775
776        bit_buf.append_n(true, 15);
777
778        assert_eq!(bit_buf.len(), 15);
779        for i in 0..15 {
780            assert!(bit_buf.value(i));
781        }
782    }
783
784    #[test]
785    fn test_mixed_operations_with_offset() {
786        // Complex test combining multiple operations with offset
787        let buf = BufferMut::zeroed(5);
788        let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
789
790        // Append some bits
791        bit_buf.append_n(true, 5);
792        bit_buf.append_n(false, 3);
793        bit_buf.append(true);
794
795        assert_eq!(bit_buf.len(), 9);
796
797        // Set and unset
798        bit_buf.set(6); // Was false, now true
799        bit_buf.unset(2); // Was true, now false
800
801        // Verify
802        assert!(bit_buf.value(0));
803        assert!(bit_buf.value(1));
804        assert!(!bit_buf.value(2)); // Unset
805        assert!(bit_buf.value(3));
806        assert!(bit_buf.value(4));
807        assert!(!bit_buf.value(5));
808        assert!(bit_buf.value(6)); // Set
809        assert!(!bit_buf.value(7));
810        assert!(bit_buf.value(8));
811
812        // Truncate
813        bit_buf.truncate(6);
814        assert_eq!(bit_buf.len(), 6);
815
816        // Freeze and verify offset preserved
817        let frozen = bit_buf.freeze();
818        assert_eq!(frozen.offset(), 3);
819        assert_eq!(frozen.len(), 6);
820    }
821}