1use std::ops::Not;
5
6use bitvec::view::BitView;
7
8use crate::BitBuffer;
9use crate::BufferAllocatorRef;
10use crate::BufferMut;
11use crate::ByteBufferMut;
12use crate::bit::collect_bool_words;
13use crate::bit::get_bit_unchecked;
14use crate::bit::ops;
15use crate::bit::pack::collect_bool_words_multiversioned;
16use crate::bit::set_bit_unchecked;
17use crate::bit::unset_bit_unchecked;
18use crate::buffer_mut;
19
20#[allow(clippy::inline_always)]
26#[inline(always)]
27pub(crate) fn fill_bits(slice: &mut [u8], start_bit: usize, end_bit: usize, value: bool) {
28 if start_bit >= end_bit {
29 return;
30 }
31 debug_assert!(end_bit <= slice.len() * 8);
32
33 let word_bits = slice.len() / 8 * 64;
34 if end_bit <= word_bits {
35 fill_word_bits(slice, start_bit, end_bit, value);
36 return;
37 }
38 if start_bit < word_bits {
39 fill_word_bits(slice, start_bit, word_bits, value);
40 }
41 fill_byte_bits(slice, start_bit.max(word_bits), end_bit, value);
42}
43
44#[allow(clippy::inline_always)]
48#[inline(always)]
49fn fill_word_bits(slice: &mut [u8], start_bit: usize, end_bit: usize, value: bool) {
50 let words = slice.as_chunks_mut::<8>().0;
51 let (start_word, start_rem) = (start_bit / 64, start_bit % 64);
52 let (end_word, end_rem) = (end_bit / 64, end_bit % 64);
53
54 if start_word == end_word {
55 fill_word_mask(
57 &mut words[start_word],
58 low_bits(end_rem) & !low_bits(start_rem),
59 value,
60 );
61 return;
62 }
63
64 fill_word_mask(&mut words[start_word], !low_bits(start_rem), value);
65 words[start_word + 1..end_word].fill(if value { [0xFF; 8] } else { [0x00; 8] });
66 if end_rem != 0 {
67 fill_word_mask(&mut words[end_word], low_bits(end_rem), value);
68 }
69}
70
71#[allow(clippy::inline_always)]
73#[inline(always)]
74const fn low_bits(n: usize) -> u64 {
75 (1u64 << n) - 1
76}
77
78#[allow(clippy::inline_always)]
80#[inline(always)]
81fn fill_word_mask(word: &mut [u8; 8], mask: u64, value: bool) {
82 let current = u64::from_le_bytes(*word);
83 let updated = if value {
84 current | mask
85 } else {
86 current & !mask
87 };
88 *word = updated.to_le_bytes();
89}
90
91#[allow(clippy::inline_always)]
93#[inline(always)]
94fn fill_byte_bits(slice: &mut [u8], start_bit: usize, end_bit: usize, value: bool) {
95 let fill_byte: u8 = if value { 0xFF } else { 0x00 };
96
97 let start_byte = start_bit / 8;
98 let start_rem = start_bit % 8;
99 let end_byte = end_bit / 8;
100 let end_rem = end_bit % 8;
101
102 if start_byte == end_byte {
103 let mask = ((1u8 << (end_rem - start_rem)) - 1) << start_rem;
105 if value {
106 slice[start_byte] |= mask;
107 } else {
108 slice[start_byte] &= !mask;
109 }
110 } else {
111 if start_rem != 0 {
113 let mask = !((1u8 << start_rem) - 1);
114 if value {
115 slice[start_byte] |= mask;
116 } else {
117 slice[start_byte] &= !mask;
118 }
119 }
120
121 let fill_start = if start_rem != 0 {
123 start_byte + 1
124 } else {
125 start_byte
126 };
127 if fill_start < end_byte {
128 slice[fill_start..end_byte].fill(fill_byte);
129 }
130
131 if end_rem != 0 {
133 let mask = (1u8 << end_rem) - 1;
134 if value {
135 slice[end_byte] |= mask;
136 } else {
137 slice[end_byte] &= !mask;
138 }
139 }
140 }
141}
142
143#[derive(Debug, Clone)]
163pub struct BitBufferMut {
164 buffer: ByteBufferMut,
165 offset: usize,
170 len: usize,
171}
172
173impl BitBufferMut {
174 #[inline]
178 pub fn from_buffer(buffer: ByteBufferMut, offset: usize, len: usize) -> Self {
179 assert!(
180 len.saturating_add(offset) <= buffer.len().saturating_mul(8),
181 "Buffer len {} is too short for offset {offset} and length {len}",
182 buffer.len()
183 );
184 Self {
185 buffer,
186 offset,
187 len,
188 }
189 }
190
191 pub fn copy_from(bit_buffer: &BitBuffer) -> Self {
193 Self::copy_from_in(bit_buffer, bit_buffer.inner().allocator().clone())
194 }
195
196 pub fn copy_from_in(bit_buffer: &BitBuffer, allocator: BufferAllocatorRef) -> Self {
198 Self {
199 buffer: ByteBufferMut::copy_from_in(bit_buffer.inner(), allocator),
200 offset: bit_buffer.offset(),
201 len: bit_buffer.len(),
202 }
203 }
204
205 #[inline]
207 pub fn with_capacity(capacity: usize) -> Self {
208 Self::with_capacity_in(capacity, BufferAllocatorRef::statically_allocated())
209 }
210
211 #[inline]
213 pub fn with_capacity_in(capacity: usize, allocator: BufferAllocatorRef) -> Self {
214 Self {
215 buffer: BufferMut::with_capacity_in(capacity.div_ceil(8), allocator),
216 offset: 0,
217 len: 0,
218 }
219 }
220
221 #[inline]
223 pub fn new_set(len: usize) -> Self {
224 Self {
225 buffer: buffer_mut![0xFF; len.div_ceil(8)],
226 offset: 0,
227 len,
228 }
229 }
230
231 #[inline]
233 pub fn new_unset(len: usize) -> Self {
234 Self {
235 buffer: BufferMut::zeroed(len.div_ceil(8)),
236 offset: 0,
237 len,
238 }
239 }
240
241 #[allow(clippy::inline_always)]
243 #[inline(always)]
244 pub fn empty() -> Self {
245 Self::with_capacity(0)
246 }
247
248 pub fn empty_in(allocator: BufferAllocatorRef) -> Self {
250 Self::with_capacity_in(0, allocator)
251 }
252
253 pub fn take(&mut self) -> Self {
255 Self {
256 buffer: self.buffer.take(),
257 offset: std::mem::take(&mut self.offset),
258 len: std::mem::take(&mut self.len),
259 }
260 }
261
262 #[inline]
264 pub fn full(value: bool, len: usize) -> Self {
265 if value {
266 Self::new_set(len)
267 } else {
268 Self::new_unset(len)
269 }
270 }
271
272 pub fn from_indices(len: usize, indices: impl IntoIterator<Item = usize>) -> BitBufferMut {
274 let mut buffer = BufferMut::<u64>::zeroed(len.div_ceil(64));
275 for idx in indices {
276 assert!(idx < len, "index {idx} exceeds len {len}");
277 buffer.as_mut_slice()[idx / 64] |= 1 << (idx % 64);
278 }
279
280 let mut buffer = buffer.into_byte_buffer();
281 buffer.truncate(len.div_ceil(8));
282
283 Self {
284 buffer,
285 offset: 0,
286 len,
287 }
288 }
289
290 #[inline]
294 pub fn collect_bool<F: FnMut(usize) -> bool>(len: usize, f: F) -> Self {
295 Self::collect_bool_in(len, f, BufferAllocatorRef::statically_allocated())
296 }
297
298 #[inline]
300 pub fn collect_bool_in<F: FnMut(usize) -> bool>(
301 len: usize,
302 f: F,
303 allocator: BufferAllocatorRef,
304 ) -> Self {
305 Self::collect_words_in(len, allocator, |words| collect_bool_words(words, len, f))
306 }
307
308 #[inline]
312 pub fn collect_bool_multiversioned<F: FnMut(usize) -> bool>(len: usize, f: F) -> Self {
313 Self::collect_bool_multiversioned_in(len, f, BufferAllocatorRef::statically_allocated())
314 }
315
316 #[inline]
318 pub fn collect_bool_multiversioned_in<F: FnMut(usize) -> bool>(
319 len: usize,
320 f: F,
321 allocator: BufferAllocatorRef,
322 ) -> Self {
323 Self::collect_words_in(len, allocator, |words| {
324 collect_bool_words_multiversioned(words, len, f)
325 })
326 }
327
328 #[inline]
329 fn collect_words_in(
330 len: usize,
331 allocator: BufferAllocatorRef,
332 fill: impl FnOnce(&mut [u64]),
333 ) -> Self {
334 let num_words = len.div_ceil(64);
335 let mut buffer = BufferMut::<u64>::zeroed_in(num_words, allocator);
340 fill(buffer.as_mut_slice());
341
342 let mut bytes = buffer.into_byte_buffer();
343 bytes.truncate(len.div_ceil(8));
344
345 Self {
346 buffer: bytes,
347 offset: 0,
348 len,
349 }
350 }
351
352 #[inline]
354 pub fn inner(&self) -> &ByteBufferMut {
355 &self.buffer
356 }
357
358 #[inline]
360 pub fn into_inner(self) -> ByteBufferMut {
361 self.buffer
362 }
363
364 #[allow(clippy::inline_always)]
366 #[inline(always)]
367 pub fn len(&self) -> usize {
368 self.len
369 }
370
371 #[allow(clippy::inline_always)]
373 #[inline(always)]
374 pub fn is_empty(&self) -> bool {
375 self.len == 0
376 }
377
378 #[allow(clippy::inline_always)]
380 #[inline(always)]
381 pub fn offset(&self) -> usize {
382 self.offset
383 }
384
385 #[allow(clippy::inline_always)]
387 #[inline(always)]
388 pub fn value(&self, index: usize) -> bool {
389 assert!(index < self.len);
390 unsafe { self.value_unchecked(index) }
392 }
393
394 #[allow(clippy::inline_always)]
400 #[inline(always)]
401 pub unsafe fn value_unchecked(&self, index: usize) -> bool {
402 unsafe { get_bit_unchecked(self.buffer.as_ptr(), self.offset + index) }
403 }
404
405 #[allow(clippy::inline_always)]
407 #[inline(always)]
408 pub fn capacity(&self) -> usize {
409 (self.buffer.capacity() * 8) - self.offset
410 }
411
412 #[inline]
414 pub fn reserve(&mut self, additional: usize) {
415 let required_bits = self.offset + self.len + additional;
416 let required_bytes = required_bits.div_ceil(8); let additional_bytes = required_bytes.saturating_sub(self.buffer.len());
419 self.buffer.reserve(additional_bytes);
420 }
421
422 #[inline]
424 pub fn clear(&mut self) {
425 self.buffer.clear();
428 self.len = 0;
429 self.offset = 0;
430 }
431
432 #[inline]
436 pub fn set_to(&mut self, index: usize, value: bool) {
437 if value {
438 self.set(index);
439 } else {
440 self.unset(index);
441 }
442 }
443
444 #[inline]
450 pub unsafe fn set_to_unchecked(&mut self, index: usize, value: bool) {
451 if value {
452 unsafe { self.set_unchecked(index) }
454 } else {
455 unsafe { self.unset_unchecked(index) }
457 }
458 }
459
460 #[inline]
464 pub fn set(&mut self, index: usize) {
465 assert!(index < self.len, "index {index} exceeds len {}", self.len);
466
467 unsafe { self.set_unchecked(index) };
469 }
470
471 #[inline]
475 pub fn unset(&mut self, index: usize) {
476 assert!(index < self.len, "index {index} exceeds len {}", self.len);
477
478 unsafe { self.unset_unchecked(index) };
480 }
481
482 #[inline]
490 pub unsafe fn set_unchecked(&mut self, index: usize) {
491 unsafe { set_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
493 }
494
495 #[inline]
503 pub unsafe fn unset_unchecked(&mut self, index: usize) {
504 unsafe { unset_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
506 }
507
508 #[allow(clippy::inline_always)]
515 #[inline(always)]
516 pub unsafe fn set_len(&mut self, new_len: usize) {
517 debug_assert!(
518 new_len <= self.capacity(),
519 "`set_len` requires that new_len <= capacity()"
520 );
521
522 let bytes_len = (self.offset + new_len).div_ceil(8);
524 unsafe { self.buffer.set_len(bytes_len) };
525
526 self.len = new_len;
527 }
528
529 #[inline]
533 pub fn truncate(&mut self, len: usize) {
534 if len > self.len {
535 return;
536 }
537
538 assert!(
539 self.offset <= usize::MAX - len,
540 "Truncate on BitBufferMut overflowed"
541 );
542 let end_bit = self.offset + len;
543 let new_len_bytes = end_bit.div_ceil(8);
544 self.buffer.truncate(new_len_bytes);
545 self.len = len;
546
547 if !end_bit.is_multiple_of(8) {
550 let keep = (1u8 << (end_bit % 8)) - 1;
551 self.buffer.as_mut_slice()[new_len_bytes - 1] &= keep;
552 }
553 }
554
555 #[inline]
557 pub fn append(&mut self, value: bool) {
558 if value {
559 self.append_true()
560 } else {
561 self.append_false()
562 }
563 }
564
565 #[inline]
567 pub fn append_true(&mut self) {
568 let bit_pos = self.offset + self.len;
569 let byte_pos = bit_pos / 8;
570 let bit_in_byte = bit_pos % 8;
571
572 if byte_pos >= self.buffer.len() {
574 self.buffer.push(0u8);
575 }
576
577 self.buffer.as_mut_slice()[byte_pos] |= 1 << bit_in_byte;
579 self.len += 1;
580 }
581
582 #[inline]
584 pub fn append_false(&mut self) {
585 let bit_pos = self.offset + self.len;
586 let byte_pos = bit_pos / 8;
587
588 if byte_pos >= self.buffer.len() {
590 self.buffer.push(0u8);
591 }
592
593 self.len += 1;
596 }
597
598 #[inline]
603 pub fn append_n(&mut self, value: bool, n: usize) {
604 if n == 0 {
605 return;
606 }
607
608 assert!(
609 self.offset
610 .checked_add(self.len)
611 .and_then(|v| v.checked_add(n))
612 .is_some(),
613 "Append on BitBufferMut overflowed"
614 );
615 let end_bit_pos = self.offset + self.len + n;
616 let required_bytes = end_bit_pos.div_ceil(8);
617
618 if required_bytes > self.buffer.len() {
620 self.buffer.push_n(0x00, required_bytes - self.buffer.len());
621 }
622
623 let start = self.offset + self.len;
624 self.len += n;
625 fill_byte_bits(self.buffer.as_mut_slice(), start, end_bit_pos, value);
628 }
629
630 #[allow(clippy::inline_always)]
635 #[inline(always)]
636 pub fn fill_range(&mut self, start: usize, end: usize, value: bool) {
637 assert!(end <= self.len, "end {end} exceeds len {}", self.len);
638 assert!(start <= end, "start {start} exceeds end {end}");
639
640 unsafe { self.fill_range_unchecked(start, end, value) }
643 }
644
645 #[allow(clippy::inline_always)]
651 #[inline(always)]
652 pub unsafe fn fill_range_unchecked(&mut self, start: usize, end: usize, value: bool) {
653 fill_bits(
654 self.buffer.as_mut_slice(),
655 self.offset + start,
656 self.offset + end,
657 value,
658 );
659 }
660
661 pub fn append_buffer(&mut self, buffer: &BitBuffer) {
665 let bit_len = buffer.len();
666 if bit_len == 0 {
667 return;
668 }
669
670 let start_bit_pos = self.offset + self.len;
671 let end_bit_pos = start_bit_pos + bit_len;
672 let required_bytes = end_bit_pos.div_ceil(8);
673
674 if required_bytes > self.buffer.len() {
676 self.buffer.push_n(0x00, required_bytes - self.buffer.len());
677 }
678
679 let dst_bit_offset = start_bit_pos % 8;
680 let src_bit_offset = buffer.offset();
681
682 if dst_bit_offset == 0 && src_bit_offset == 0 {
683 let dst_byte = start_bit_pos / 8;
685 let src_bytes = buffer.inner().as_slice();
686 let full_bytes = bit_len / 8;
687 self.buffer.as_mut_slice()[dst_byte..dst_byte + full_bytes]
688 .copy_from_slice(&src_bytes[..full_bytes]);
689 let rem = bit_len % 8;
690 if rem != 0 {
691 let mask = (1u8 << rem) - 1;
692 self.buffer.as_mut_slice()[dst_byte + full_bytes] |= src_bytes[full_bytes] & mask;
693 }
694 } else {
695 let self_slice = self
697 .buffer
698 .as_mut_slice()
699 .view_bits_mut::<bitvec::prelude::Lsb0>();
700 let other_slice = buffer
701 .inner()
702 .as_slice()
703 .view_bits::<bitvec::prelude::Lsb0>();
704 let source_range = src_bit_offset..src_bit_offset + bit_len;
705 self_slice[start_bit_pos..end_bit_pos].copy_from_bitslice(&other_slice[source_range]);
706 }
707
708 self.len += bit_len;
709 }
710
711 #[inline]
713 pub fn freeze(self) -> BitBuffer {
714 BitBuffer::new_with_offset(self.buffer.freeze(), self.len, self.offset)
715 }
716
717 #[inline]
719 pub fn as_slice(&self) -> &[u8] {
720 self.buffer.as_slice()
721 }
722
723 #[inline]
725 pub fn as_mut_slice(&mut self) -> &mut [u8] {
726 self.buffer.as_mut_slice()
727 }
728}
729
730impl Default for BitBufferMut {
731 fn default() -> Self {
732 Self::with_capacity(0)
733 }
734}
735
736impl Not for BitBufferMut {
738 type Output = BitBufferMut;
739
740 #[inline]
741 fn not(mut self) -> Self::Output {
742 ops::bitwise_unary_op_mut(&mut self, |b| !b);
743 self
744 }
745}
746
747impl From<&[bool]> for BitBufferMut {
748 fn from(value: &[bool]) -> Self {
749 BitBufferMut::collect_bool_multiversioned(value.len(), |i| unsafe {
752 *value.get_unchecked(i)
753 })
754 }
755}
756
757impl From<&[u8]> for BitBufferMut {
759 fn from(value: &[u8]) -> Self {
760 BitBufferMut::collect_bool_multiversioned(
763 value.len(),
764 |i| unsafe { *value.get_unchecked(i) } > 0,
765 )
766 }
767}
768
769impl From<Vec<bool>> for BitBufferMut {
770 fn from(value: Vec<bool>) -> Self {
771 value.as_slice().into()
772 }
773}
774
775impl FromIterator<bool> for BitBufferMut {
776 #[inline]
777 fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
778 let mut iter = iter.into_iter();
779
780 let (lower_bound, _) = iter.size_hint();
783
784 let mut buf = BitBufferMut::new_unset(lower_bound);
789 assert_eq!(buf.offset, 0);
790
791 let ptr = buf.buffer.as_mut_ptr();
793 for i in 0..lower_bound {
794 let Some(v) = iter.next() else {
795 unsafe { buf.set_len(i) };
798 return buf;
799 };
800
801 if v {
802 unsafe { set_bit_unchecked(ptr, i) }
804 }
805 }
806
807 for v in iter {
810 buf.append(v);
811 }
812
813 buf
814 }
815}
816
817#[cfg(test)]
818mod tests {
819 use allocator_api2::alloc::Global;
820 use rstest::rstest;
821
822 use crate::BufferAllocatorRef;
823 use crate::BufferMut;
824 use crate::bit::buf_mut::BitBufferMut;
825 use crate::bit::buf_mut::fill_bits;
826 use crate::bitbuffer;
827 use crate::bitbuffer_mut;
828 use crate::buffer_mut;
829
830 #[rstest]
833 fn fill_bits_matches_bitwise_fill(
834 #[values(1, 7, 8, 9, 16, 17)] slice_len: usize,
835 #[values(false, true)] value: bool,
836 ) {
837 let pattern: Vec<u8> = (0u8..)
838 .take(slice_len)
839 .map(|i| i.wrapping_mul(0x5B) ^ 0xA6)
840 .collect();
841 for start in 0..=slice_len * 8 {
842 for end in start..=slice_len * 8 {
843 let mut actual = pattern.clone();
844 fill_bits(&mut actual, start, end, value);
845
846 let mut expected = pattern.clone();
847 for bit in start..end {
848 if value {
849 expected[bit / 8] |= 1 << (bit % 8);
850 } else {
851 expected[bit / 8] &= !(1 << (bit % 8));
852 }
853 }
854 assert_eq!(actual, expected, "range {start}..{end}");
855 }
856 }
857 }
858
859 #[test]
860 fn test_bits_mut() {
861 let mut bools = bitbuffer_mut![false; 10];
862 bools.set_to(0, true);
863 bools.set_to(9, true);
864
865 let bools = bools.freeze();
866 assert!(bools.value(0));
867 for i in 1..=8 {
868 assert!(!bools.value(i));
869 }
870 assert!(bools.value(9));
871 }
872
873 #[test]
874 fn take_preserves_allocator() {
875 let allocator = BufferAllocatorRef::new(Global);
876 let mut buffer = BitBufferMut::with_capacity_in(4, allocator.clone());
877 buffer.append(true);
878 buffer.append(false);
879 buffer.append(true);
880
881 let taken = buffer.take();
882
883 assert_eq!(
884 (0..taken.len())
885 .map(|index| taken.value(index))
886 .collect::<Vec<_>>(),
887 [true, false, true]
888 );
889 assert!(taken.buffer.allocation.allocator().ptr_eq(&allocator));
890 assert!(buffer.is_empty());
891 assert!(buffer.buffer.allocation.allocator().ptr_eq(&allocator));
892 }
893
894 #[test]
895 fn test_append_n() {
896 let mut bools = BitBufferMut::with_capacity(10);
897 assert_eq!(bools.len(), 0);
898 assert!(bools.is_empty());
899
900 bools.append(true);
901 bools.append_n(false, 8);
902 bools.append_n(true, 1);
903
904 let bools = bools.freeze();
905
906 assert_eq!(bools.true_count(), 2);
907 assert!(bools.value(0));
908 assert!(bools.value(9));
909 }
910
911 #[test]
912 fn append_false_after_truncate_reads_back_false() {
913 let mut bools = BitBufferMut::new_set(16);
916 bools.truncate(12);
917 bools.append_false();
918 bools.append_true();
919
920 let bools = bools.freeze();
921 assert_eq!(bools.len(), 14);
922 assert!(
923 !bools.value(12),
924 "appended false must read back false after truncate"
925 );
926 assert!(bools.value(13));
927 }
928
929 #[test]
930 fn test_reserve_ensures_len_plus_additional() {
931 let mut bits = BitBufferMut::with_capacity(10);
935 assert_eq!(bits.len(), 0);
936
937 bits.reserve(100);
938
939 assert!(bits.capacity() >= 100);
941
942 bits.append_n(true, 50);
943 assert_eq!(bits.len(), 50);
944
945 bits.reserve(100);
946
947 assert!(bits.capacity() >= 150);
949 }
950
951 #[test]
952 fn test_with_offset_zero() {
953 let buf = BufferMut::zeroed(2);
955 let mut bit_buf = BitBufferMut::from_buffer(buf, 0, 16);
956
957 bit_buf.set(0);
959 bit_buf.set(7);
960 bit_buf.set(8);
961 bit_buf.set(15);
962
963 assert!(bit_buf.value(0));
965 assert!(bit_buf.value(7));
966 assert!(bit_buf.value(8));
967 assert!(bit_buf.value(15));
968 assert!(!bit_buf.value(1));
969 assert!(!bit_buf.value(9));
970
971 assert_eq!(bit_buf.as_slice()[0], 0b10000001);
973 assert_eq!(bit_buf.as_slice()[1], 0b10000001);
974 }
975
976 #[test]
977 fn test_with_offset_within_byte() {
978 let buf = buffer_mut![0b11111111, 0b00000000, 0b00000000];
980 let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 10);
981
982 assert!(bit_buf.value(0)); assert!(bit_buf.value(4)); assert!(!bit_buf.value(5)); bit_buf.set(7);
990 assert!(bit_buf.value(7));
991
992 bit_buf.unset(0);
994 assert!(!bit_buf.value(0));
995 }
996
997 #[test]
998 fn test_with_offset_byte_boundary() {
999 let buf = buffer_mut![0xFF, 0x00, 0xFF];
1001 let mut bit_buf = BitBufferMut::from_buffer(buf, 8, 16);
1002
1003 for i in 0..8 {
1005 assert!(!bit_buf.value(i));
1006 }
1007 for i in 8..16 {
1009 assert!(bit_buf.value(i));
1010 }
1011
1012 bit_buf.set(0);
1014 bit_buf.set(3);
1015 assert!(bit_buf.value(0));
1016 assert!(bit_buf.value(3));
1017 }
1018
1019 #[test]
1020 fn test_with_large_offset() {
1021 let buf = buffer_mut![0xFF, 0xFF, 0xFF, 0xFF];
1023 let mut bit_buf = BitBufferMut::from_buffer(buf, 13, 10);
1024
1025 for i in 0..10 {
1027 assert!(bit_buf.value(i));
1028 }
1029
1030 bit_buf.unset(0);
1032 bit_buf.unset(5);
1033 bit_buf.unset(9);
1034
1035 assert!(!bit_buf.value(0));
1036 assert!(bit_buf.value(1));
1037 assert!(!bit_buf.value(5));
1038 assert!(!bit_buf.value(9));
1039 }
1040
1041 #[test]
1042 fn test_append_with_offset() {
1043 let buf = buffer_mut![0b11100000]; let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0); bit_buf.append(false); bit_buf.append(true); bit_buf.append(true); assert_eq!(bit_buf.len(), 3);
1053 assert!(!bit_buf.value(0));
1054 assert!(bit_buf.value(1));
1055 assert!(bit_buf.value(2));
1056 }
1057
1058 #[test]
1059 fn test_append_n_with_offset_crossing_boundary() {
1060 let buf = BufferMut::zeroed(4);
1062 let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1063
1064 bit_buf.append_n(true, 10); assert_eq!(bit_buf.len(), 10);
1068 for i in 0..10 {
1069 assert!(bit_buf.value(i));
1070 }
1071
1072 assert_eq!(bit_buf.as_slice()[0], 0b11100000);
1076 assert_eq!(bit_buf.as_slice()[1], 0b01111111);
1077 }
1078
1079 #[test]
1080 fn test_truncate_with_offset() {
1081 let buf = buffer_mut![0xFF, 0xFF];
1082 let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 12);
1083
1084 assert_eq!(bit_buf.len(), 12);
1085
1086 bit_buf.truncate(8);
1088 assert_eq!(bit_buf.len(), 8);
1089
1090 bit_buf.truncate(3);
1092 assert_eq!(bit_buf.len(), 3);
1093
1094 bit_buf.truncate(10);
1096 assert_eq!(bit_buf.len(), 3);
1097 }
1098
1099 #[test]
1100 fn test_capacity_with_offset() {
1101 let buf = buffer_mut![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1104
1105 assert!(bit_buf.capacity() >= 75);
1108 assert_eq!(bit_buf.capacity() % 8, (80 - 5) % 8);
1110 }
1111
1112 #[test]
1113 fn test_reserve_with_offset() {
1114 let buf = buffer_mut![0, 0]; let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
1117
1118 let initial_capacity = bit_buf.capacity();
1120 assert!(initial_capacity >= 13);
1121
1122 bit_buf.reserve(20);
1124
1125 assert!(bit_buf.capacity() >= 20);
1127 }
1128
1129 #[test]
1130 fn test_freeze_with_offset() {
1131 let buf = buffer_mut![0b11110000, 0b00001111];
1132 let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
1133
1134 bit_buf.set(0);
1136 bit_buf.set(7);
1137
1138 let frozen = bit_buf.freeze();
1140 assert_eq!(frozen.offset(), 4);
1141 assert_eq!(frozen.len(), 8);
1142
1143 assert!(frozen.value(0));
1145 assert!(frozen.value(7));
1146 }
1147
1148 #[cfg_attr(miri, ignore)] #[test]
1150 fn append_after_clear_reads_back_false() {
1151 let mut bools = BitBufferMut::new_set(16);
1154 bools.clear();
1155 bools.append_false();
1156 bools.append_buffer(&crate::BitBuffer::new_unset(8));
1157
1158 let bools = bools.freeze();
1159 assert_eq!(bools.len(), 9);
1160 assert_eq!(bools.true_count(), 0);
1161 }
1162
1163 #[cfg_attr(miri, ignore)] #[test]
1165 fn test_append_buffer_after_truncate() {
1166 let mut buf = BitBufferMut::new_set(16);
1169 buf.truncate(3);
1170 buf.append_buffer(&crate::BitBuffer::new_unset(8));
1171
1172 let frozen = buf.freeze();
1173 assert_eq!(frozen.len(), 11);
1174 for i in 0..3 {
1175 assert!(frozen.value(i), "bit {i} should be set");
1176 }
1177 for i in 3..11 {
1178 assert!(!frozen.value(i), "bit {i} should be unset");
1179 }
1180 }
1181
1182 #[rstest]
1183 #[case::both_aligned(0, 0)]
1184 #[case::dst_unaligned(3, 0)]
1185 #[case::src_unaligned(0, 5)]
1186 #[case::mismatched(3, 5)]
1187 #[case::equal_nonzero(5, 5)]
1188 #[cfg_attr(miri, ignore)] fn test_append_buffer_long(#[case] dst_prefix: usize, #[case] src_start: usize) {
1190 let source = crate::BitBuffer::from_iter((0..301).map(|i| i % 3 == 0));
1192 let source = source.slice(src_start..301);
1193
1194 let mut dest = BitBufferMut::with_capacity(512);
1195 dest.append_n(true, dst_prefix);
1196 dest.append_buffer(&source);
1197
1198 assert_eq!(dest.len(), dst_prefix + source.len());
1199 for i in 0..dst_prefix {
1200 assert!(dest.value(i), "prefix bit {i}");
1201 }
1202 for i in 0..source.len() {
1203 assert_eq!(dest.value(dst_prefix + i), source.value(i), "bit {i}");
1204 }
1205 }
1206
1207 #[cfg_attr(miri, ignore)] #[test]
1209 fn test_append_buffer_with_offsets() {
1210 let source = bitbuffer![false, false, true, true, false, true];
1212
1213 let buf = BufferMut::zeroed(4);
1215 let mut dest = BitBufferMut::from_buffer(buf, 3, 0);
1216
1217 dest.append(true);
1219 dest.append(false);
1220
1221 dest.append_buffer(&source);
1223
1224 assert_eq!(dest.len(), 8);
1225 assert!(dest.value(0)); assert!(!dest.value(1)); assert!(!dest.value(2)); assert!(!dest.value(3)); assert!(dest.value(4)); assert!(dest.value(5)); assert!(!dest.value(6)); assert!(dest.value(7)); }
1234
1235 #[test]
1236 fn test_set_unset_unchecked_with_offset() {
1237 let buf = BufferMut::zeroed(3);
1238 let mut bit_buf = BitBufferMut::from_buffer(buf, 7, 10);
1239
1240 unsafe {
1241 bit_buf.set_unchecked(0);
1242 bit_buf.set_unchecked(5);
1243 bit_buf.set_unchecked(9);
1244 }
1245
1246 assert!(bit_buf.value(0));
1247 assert!(bit_buf.value(5));
1248 assert!(bit_buf.value(9));
1249
1250 unsafe {
1251 bit_buf.unset_unchecked(5);
1252 }
1253
1254 assert!(!bit_buf.value(5));
1255 }
1256
1257 #[test]
1258 fn test_value_unchecked_with_offset() {
1259 let buf = buffer_mut![0b11110000, 0b00001111];
1260 let bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
1261
1262 unsafe {
1263 assert!(bit_buf.value_unchecked(0));
1265 assert!(bit_buf.value_unchecked(3));
1266
1267 assert!(bit_buf.value_unchecked(4));
1269 assert!(bit_buf.value_unchecked(7));
1270 }
1271 }
1272
1273 #[test]
1274 fn test_append_alternating_with_offset() {
1275 let buf = BufferMut::zeroed(4);
1276 let mut bit_buf = BitBufferMut::from_buffer(buf, 2, 0);
1277
1278 for i in 0..20 {
1280 bit_buf.append(i % 2 == 0);
1281 }
1282
1283 assert_eq!(bit_buf.len(), 20);
1284 for i in 0..20 {
1285 assert_eq!(bit_buf.value(i), i % 2 == 0);
1286 }
1287 }
1288
1289 #[test]
1290 fn test_new_set_new_unset() {
1291 let set_buf = bitbuffer_mut![true; 10];
1292 let unset_buf = bitbuffer_mut![false; 10];
1293
1294 for i in 0..10 {
1295 assert!(set_buf.value(i));
1296 assert!(!unset_buf.value(i));
1297 }
1298
1299 assert_eq!(set_buf.len(), 10);
1300 assert_eq!(unset_buf.len(), 10);
1301 }
1302
1303 #[test]
1304 fn test_append_n_false_with_offset() {
1305 let buf = BufferMut::zeroed(4);
1306 let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1307
1308 bit_buf.append_n(false, 15);
1309
1310 assert_eq!(bit_buf.len(), 15);
1311 for i in 0..15 {
1312 assert!(!bit_buf.value(i));
1313 }
1314 }
1315
1316 #[test]
1317 fn test_append_n_true_with_offset() {
1318 let buf = BufferMut::zeroed(4);
1319 let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1320
1321 bit_buf.append_n(true, 15);
1322
1323 assert_eq!(bit_buf.len(), 15);
1324 for i in 0..15 {
1325 assert!(bit_buf.value(i));
1326 }
1327 }
1328
1329 #[test]
1330 fn test_mixed_operations_with_offset() {
1331 let buf = BufferMut::zeroed(5);
1333 let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
1334
1335 bit_buf.append_n(true, 5);
1337 bit_buf.append_n(false, 3);
1338 bit_buf.append(true);
1339
1340 assert_eq!(bit_buf.len(), 9);
1341
1342 bit_buf.set(6); bit_buf.unset(2); assert!(bit_buf.value(0));
1348 assert!(bit_buf.value(1));
1349 assert!(!bit_buf.value(2)); assert!(bit_buf.value(3));
1351 assert!(bit_buf.value(4));
1352 assert!(!bit_buf.value(5));
1353 assert!(bit_buf.value(6)); assert!(!bit_buf.value(7));
1355 assert!(bit_buf.value(8));
1356
1357 bit_buf.truncate(6);
1359 assert_eq!(bit_buf.len(), 6);
1360
1361 let frozen = bit_buf.freeze();
1363 assert_eq!(frozen.offset(), 3);
1364 assert_eq!(frozen.len(), 6);
1365 }
1366
1367 #[test]
1368 fn test_from_iterator_with_incorrect_size_hint() {
1369 struct LyingIterator {
1376 values: Vec<bool>,
1377 index: usize,
1378 }
1379
1380 impl Iterator for LyingIterator {
1381 type Item = bool;
1382
1383 fn next(&mut self) -> Option<Self::Item> {
1384 (self.index < self.values.len()).then(|| {
1385 let val = self.values[self.index];
1386 self.index += 1;
1387 val
1388 })
1389 }
1390
1391 fn size_hint(&self) -> (usize, Option<usize>) {
1392 let remaining = self.values.len() - self.index;
1395 let lower = remaining.min(5); let upper = Some(5); (lower, upper)
1398 }
1399 }
1400
1401 let lying_iter = LyingIterator {
1403 values: vec![
1404 true, false, true, false, true, false, true, false, true, false,
1405 ],
1406 index: 0,
1407 };
1408
1409 let bit_buf: BitBufferMut = lying_iter.collect();
1412
1413 assert_eq!(bit_buf.len(), 10);
1415 for i in 0..10 {
1416 assert_eq!(bit_buf.value(i), i % 2 == 0);
1417 }
1418 }
1419
1420 #[rstest]
1424 #[case(0, 8)]
1425 #[case(1, 7)]
1426 #[case(7, 1)]
1427 #[case(8, 0)]
1428 fn from_buffer_accepts_offset_plus_len_within_the_buffer(
1429 #[case] offset: usize,
1430 #[case] len: usize,
1431 ) {
1432 let bits = BitBufferMut::from_buffer(buffer_mut![0u8; 1], offset, len);
1433 assert_eq!(bits.len(), len);
1434 }
1435
1436 #[rstest]
1437 #[case::offset_pushes_past_the_end(1, 8)]
1438 #[case::offset_alone_past_the_end(9, 0)]
1439 #[case::len_alone_past_the_end(0, 9)]
1440 #[should_panic(expected = "is too short for offset")]
1441 fn from_buffer_rejects_offset_plus_len_past_the_buffer(
1442 #[case] offset: usize,
1443 #[case] len: usize,
1444 ) {
1445 BitBufferMut::from_buffer(buffer_mut![0u8; 1], offset, len);
1446 }
1447
1448 #[test]
1451 fn from_buffer_allows_offsets_beyond_one_byte() {
1452 let bits = BitBufferMut::from_buffer(buffer_mut![0u8; 128], 1000, 24);
1453 assert_eq!(bits.len(), 24);
1454 }
1455
1456 #[test]
1458 #[should_panic(expected = "is too short for offset")]
1459 fn from_buffer_does_not_wrap_on_a_huge_offset() {
1460 BitBufferMut::from_buffer(buffer_mut![0u8; 1], usize::MAX, 8);
1461 }
1462}