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 #[cfg(test)]
254 pub(crate) fn allocator(&self) -> &BufferAllocatorRef {
255 self.buffer.allocator()
256 }
257
258 pub fn take(&mut self) -> Self {
260 Self {
261 buffer: self.buffer.take(),
262 offset: std::mem::take(&mut self.offset),
263 len: std::mem::take(&mut self.len),
264 }
265 }
266
267 #[inline]
269 pub fn full(value: bool, len: usize) -> Self {
270 if value {
271 Self::new_set(len)
272 } else {
273 Self::new_unset(len)
274 }
275 }
276
277 pub fn from_indices(len: usize, indices: impl IntoIterator<Item = usize>) -> BitBufferMut {
279 let mut buffer = BufferMut::<u64>::zeroed(len.div_ceil(64));
280 for idx in indices {
281 assert!(idx < len, "index {idx} exceeds len {len}");
282 buffer.as_mut_slice()[idx / 64] |= 1 << (idx % 64);
283 }
284
285 let mut buffer = buffer.into_byte_buffer();
286 buffer.truncate(len.div_ceil(8));
287
288 Self {
289 buffer,
290 offset: 0,
291 len,
292 }
293 }
294
295 #[inline]
299 pub fn collect_bool<F: FnMut(usize) -> bool>(len: usize, f: F) -> Self {
300 Self::collect_bool_in(len, f, BufferAllocatorRef::statically_allocated())
301 }
302
303 #[inline]
305 pub fn collect_bool_in<F: FnMut(usize) -> bool>(
306 len: usize,
307 f: F,
308 allocator: BufferAllocatorRef,
309 ) -> Self {
310 Self::collect_words_in(len, allocator, |words| collect_bool_words(words, len, f))
311 }
312
313 #[inline]
317 pub fn collect_bool_multiversioned<F: FnMut(usize) -> bool>(len: usize, f: F) -> Self {
318 Self::collect_bool_multiversioned_in(len, f, BufferAllocatorRef::statically_allocated())
319 }
320
321 #[inline]
323 pub fn collect_bool_multiversioned_in<F: FnMut(usize) -> bool>(
324 len: usize,
325 f: F,
326 allocator: BufferAllocatorRef,
327 ) -> Self {
328 Self::collect_words_in(len, allocator, |words| {
329 collect_bool_words_multiversioned(words, len, f)
330 })
331 }
332
333 #[inline]
334 fn collect_words_in(
335 len: usize,
336 allocator: BufferAllocatorRef,
337 fill: impl FnOnce(&mut [u64]),
338 ) -> Self {
339 let num_words = len.div_ceil(64);
340 let mut buffer = BufferMut::<u64>::zeroed_in(num_words, allocator);
345 fill(buffer.as_mut_slice());
346
347 let mut bytes = buffer.into_byte_buffer();
348 bytes.truncate(len.div_ceil(8));
349
350 Self {
351 buffer: bytes,
352 offset: 0,
353 len,
354 }
355 }
356
357 #[inline]
359 pub fn inner(&self) -> &ByteBufferMut {
360 &self.buffer
361 }
362
363 #[inline]
365 pub fn into_inner(self) -> ByteBufferMut {
366 self.buffer
367 }
368
369 #[allow(clippy::inline_always)]
371 #[inline(always)]
372 pub fn len(&self) -> usize {
373 self.len
374 }
375
376 #[allow(clippy::inline_always)]
378 #[inline(always)]
379 pub fn is_empty(&self) -> bool {
380 self.len == 0
381 }
382
383 #[allow(clippy::inline_always)]
385 #[inline(always)]
386 pub fn offset(&self) -> usize {
387 self.offset
388 }
389
390 #[allow(clippy::inline_always)]
392 #[inline(always)]
393 pub fn value(&self, index: usize) -> bool {
394 assert!(index < self.len);
395 unsafe { self.value_unchecked(index) }
397 }
398
399 #[allow(clippy::inline_always)]
405 #[inline(always)]
406 pub unsafe fn value_unchecked(&self, index: usize) -> bool {
407 unsafe { get_bit_unchecked(self.buffer.as_ptr(), self.offset + index) }
408 }
409
410 #[allow(clippy::inline_always)]
412 #[inline(always)]
413 pub fn capacity(&self) -> usize {
414 (self.buffer.capacity() * 8) - self.offset
415 }
416
417 #[inline]
419 pub fn reserve(&mut self, additional: usize) {
420 let required_bits = self.offset + self.len + additional;
421 let required_bytes = required_bits.div_ceil(8); let additional_bytes = required_bytes.saturating_sub(self.buffer.len());
424 self.buffer.reserve(additional_bytes);
425 }
426
427 #[inline]
429 pub fn clear(&mut self) {
430 self.buffer.clear();
433 self.len = 0;
434 self.offset = 0;
435 }
436
437 #[inline]
441 pub fn set_to(&mut self, index: usize, value: bool) {
442 if value {
443 self.set(index);
444 } else {
445 self.unset(index);
446 }
447 }
448
449 #[inline]
455 pub unsafe fn set_to_unchecked(&mut self, index: usize, value: bool) {
456 if value {
457 unsafe { self.set_unchecked(index) }
459 } else {
460 unsafe { self.unset_unchecked(index) }
462 }
463 }
464
465 #[inline]
469 pub fn set(&mut self, index: usize) {
470 assert!(index < self.len, "index {index} exceeds len {}", self.len);
471
472 unsafe { self.set_unchecked(index) };
474 }
475
476 #[inline]
480 pub fn unset(&mut self, index: usize) {
481 assert!(index < self.len, "index {index} exceeds len {}", self.len);
482
483 unsafe { self.unset_unchecked(index) };
485 }
486
487 #[inline]
495 pub unsafe fn set_unchecked(&mut self, index: usize) {
496 unsafe { set_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
498 }
499
500 #[inline]
508 pub unsafe fn unset_unchecked(&mut self, index: usize) {
509 unsafe { unset_bit_unchecked(self.buffer.as_mut_ptr(), self.offset + index) }
511 }
512
513 #[allow(clippy::inline_always)]
520 #[inline(always)]
521 pub unsafe fn set_len(&mut self, new_len: usize) {
522 debug_assert!(
523 new_len <= self.capacity(),
524 "`set_len` requires that new_len <= capacity()"
525 );
526
527 let bytes_len = (self.offset + new_len).div_ceil(8);
529 unsafe { self.buffer.set_len(bytes_len) };
530
531 self.len = new_len;
532 }
533
534 #[inline]
538 pub fn truncate(&mut self, len: usize) {
539 if len > self.len {
540 return;
541 }
542
543 assert!(
544 self.offset <= usize::MAX - len,
545 "Truncate on BitBufferMut overflowed"
546 );
547 let end_bit = self.offset + len;
548 let new_len_bytes = end_bit.div_ceil(8);
549 self.buffer.truncate(new_len_bytes);
550 self.len = len;
551
552 if !end_bit.is_multiple_of(8) {
555 let keep = (1u8 << (end_bit % 8)) - 1;
556 self.buffer.as_mut_slice()[new_len_bytes - 1] &= keep;
557 }
558 }
559
560 #[inline]
562 pub fn append(&mut self, value: bool) {
563 if value {
564 self.append_true()
565 } else {
566 self.append_false()
567 }
568 }
569
570 #[inline]
572 pub fn append_true(&mut self) {
573 let bit_pos = self.offset + self.len;
574 let byte_pos = bit_pos / 8;
575 let bit_in_byte = bit_pos % 8;
576
577 if byte_pos >= self.buffer.len() {
579 self.buffer.push(0u8);
580 }
581
582 self.buffer.as_mut_slice()[byte_pos] |= 1 << bit_in_byte;
584 self.len += 1;
585 }
586
587 #[inline]
589 pub fn append_false(&mut self) {
590 let bit_pos = self.offset + self.len;
591 let byte_pos = bit_pos / 8;
592
593 if byte_pos >= self.buffer.len() {
595 self.buffer.push(0u8);
596 }
597
598 self.len += 1;
601 }
602
603 #[inline]
608 pub fn append_n(&mut self, value: bool, n: usize) {
609 if n == 0 {
610 return;
611 }
612
613 assert!(
614 self.offset
615 .checked_add(self.len)
616 .and_then(|v| v.checked_add(n))
617 .is_some(),
618 "Append on BitBufferMut overflowed"
619 );
620 let end_bit_pos = self.offset + self.len + n;
621 let required_bytes = end_bit_pos.div_ceil(8);
622
623 if required_bytes > self.buffer.len() {
625 self.buffer.push_n(0x00, required_bytes - self.buffer.len());
626 }
627
628 let start = self.offset + self.len;
629 self.len += n;
630 fill_byte_bits(self.buffer.as_mut_slice(), start, end_bit_pos, value);
633 }
634
635 #[allow(clippy::inline_always)]
640 #[inline(always)]
641 pub fn fill_range(&mut self, start: usize, end: usize, value: bool) {
642 assert!(end <= self.len, "end {end} exceeds len {}", self.len);
643 assert!(start <= end, "start {start} exceeds end {end}");
644
645 unsafe { self.fill_range_unchecked(start, end, value) }
648 }
649
650 #[allow(clippy::inline_always)]
656 #[inline(always)]
657 pub unsafe fn fill_range_unchecked(&mut self, start: usize, end: usize, value: bool) {
658 fill_bits(
659 self.buffer.as_mut_slice(),
660 self.offset + start,
661 self.offset + end,
662 value,
663 );
664 }
665
666 pub fn append_buffer(&mut self, buffer: &BitBuffer) {
670 let bit_len = buffer.len();
671 if bit_len == 0 {
672 return;
673 }
674
675 let start_bit_pos = self.offset + self.len;
676 let end_bit_pos = start_bit_pos + bit_len;
677 let required_bytes = end_bit_pos.div_ceil(8);
678
679 if required_bytes > self.buffer.len() {
681 self.buffer.push_n(0x00, required_bytes - self.buffer.len());
682 }
683
684 let dst_bit_offset = start_bit_pos % 8;
685 let src_bit_offset = buffer.offset();
686
687 if dst_bit_offset == 0 && src_bit_offset == 0 {
688 let dst_byte = start_bit_pos / 8;
690 let src_bytes = buffer.inner().as_slice();
691 let full_bytes = bit_len / 8;
692 self.buffer.as_mut_slice()[dst_byte..dst_byte + full_bytes]
693 .copy_from_slice(&src_bytes[..full_bytes]);
694 let rem = bit_len % 8;
695 if rem != 0 {
696 let mask = (1u8 << rem) - 1;
697 self.buffer.as_mut_slice()[dst_byte + full_bytes] |= src_bytes[full_bytes] & mask;
698 }
699 } else {
700 let self_slice = self
702 .buffer
703 .as_mut_slice()
704 .view_bits_mut::<bitvec::prelude::Lsb0>();
705 let other_slice = buffer
706 .inner()
707 .as_slice()
708 .view_bits::<bitvec::prelude::Lsb0>();
709 let source_range = src_bit_offset..src_bit_offset + bit_len;
710 self_slice[start_bit_pos..end_bit_pos].copy_from_bitslice(&other_slice[source_range]);
711 }
712
713 self.len += bit_len;
714 }
715
716 #[inline]
718 pub fn freeze(self) -> BitBuffer {
719 BitBuffer::new_with_offset(self.buffer.freeze(), self.len, self.offset)
720 }
721
722 #[inline]
724 pub fn as_slice(&self) -> &[u8] {
725 self.buffer.as_slice()
726 }
727
728 #[inline]
730 pub fn as_mut_slice(&mut self) -> &mut [u8] {
731 self.buffer.as_mut_slice()
732 }
733}
734
735impl Default for BitBufferMut {
736 fn default() -> Self {
737 Self::with_capacity(0)
738 }
739}
740
741impl Not for BitBufferMut {
743 type Output = BitBufferMut;
744
745 #[inline]
746 fn not(mut self) -> Self::Output {
747 ops::bitwise_unary_op_mut(&mut self, |b| !b);
748 self
749 }
750}
751
752impl From<&[bool]> for BitBufferMut {
753 fn from(value: &[bool]) -> Self {
754 BitBufferMut::collect_bool_multiversioned(value.len(), |i| unsafe {
757 *value.get_unchecked(i)
758 })
759 }
760}
761
762impl From<&[u8]> for BitBufferMut {
764 fn from(value: &[u8]) -> Self {
765 BitBufferMut::collect_bool_multiversioned(
768 value.len(),
769 |i| unsafe { *value.get_unchecked(i) } > 0,
770 )
771 }
772}
773
774impl From<Vec<bool>> for BitBufferMut {
775 fn from(value: Vec<bool>) -> Self {
776 value.as_slice().into()
777 }
778}
779
780impl FromIterator<bool> for BitBufferMut {
781 #[inline]
782 fn from_iter<T: IntoIterator<Item = bool>>(iter: T) -> Self {
783 let mut iter = iter.into_iter();
784
785 let (lower_bound, _) = iter.size_hint();
788
789 let mut buf = BitBufferMut::new_unset(lower_bound);
794 assert_eq!(buf.offset, 0);
795
796 let ptr = buf.buffer.as_mut_ptr();
798 for i in 0..lower_bound {
799 let Some(v) = iter.next() else {
800 unsafe { buf.set_len(i) };
803 return buf;
804 };
805
806 if v {
807 unsafe { set_bit_unchecked(ptr, i) }
809 }
810 }
811
812 for v in iter {
815 buf.append(v);
816 }
817
818 buf
819 }
820}
821
822#[cfg(test)]
823mod tests {
824 use allocator_api2::alloc::Global;
825 use rstest::rstest;
826
827 use crate::BufferAllocatorRef;
828 use crate::BufferMut;
829 use crate::bit::buf_mut::BitBufferMut;
830 use crate::bit::buf_mut::fill_bits;
831 use crate::bitbuffer;
832 use crate::bitbuffer_mut;
833 use crate::buffer_mut;
834
835 #[rstest]
838 fn fill_bits_matches_bitwise_fill(
839 #[values(1, 7, 8, 9, 16, 17)] slice_len: usize,
840 #[values(false, true)] value: bool,
841 ) {
842 let pattern: Vec<u8> = (0u8..)
843 .take(slice_len)
844 .map(|i| i.wrapping_mul(0x5B) ^ 0xA6)
845 .collect();
846 for start in 0..=slice_len * 8 {
847 for end in start..=slice_len * 8 {
848 let mut actual = pattern.clone();
849 fill_bits(&mut actual, start, end, value);
850
851 let mut expected = pattern.clone();
852 for bit in start..end {
853 if value {
854 expected[bit / 8] |= 1 << (bit % 8);
855 } else {
856 expected[bit / 8] &= !(1 << (bit % 8));
857 }
858 }
859 assert_eq!(actual, expected, "range {start}..{end}");
860 }
861 }
862 }
863
864 #[test]
865 fn test_bits_mut() {
866 let mut bools = bitbuffer_mut![false; 10];
867 bools.set_to(0, true);
868 bools.set_to(9, true);
869
870 let bools = bools.freeze();
871 assert!(bools.value(0));
872 for i in 1..=8 {
873 assert!(!bools.value(i));
874 }
875 assert!(bools.value(9));
876 }
877
878 #[test]
879 fn take_preserves_allocator() {
880 let allocator = BufferAllocatorRef::new(Global);
881 let mut buffer = BitBufferMut::with_capacity_in(4, allocator.clone());
882 buffer.append(true);
883 buffer.append(false);
884 buffer.append(true);
885
886 let taken = buffer.take();
887
888 assert_eq!(
889 (0..taken.len())
890 .map(|index| taken.value(index))
891 .collect::<Vec<_>>(),
892 [true, false, true]
893 );
894 assert!(taken.allocator().ptr_eq(&allocator));
895 assert!(buffer.is_empty());
896 assert!(buffer.allocator().ptr_eq(&allocator));
897 }
898
899 #[test]
900 fn test_append_n() {
901 let mut bools = BitBufferMut::with_capacity(10);
902 assert_eq!(bools.len(), 0);
903 assert!(bools.is_empty());
904
905 bools.append(true);
906 bools.append_n(false, 8);
907 bools.append_n(true, 1);
908
909 let bools = bools.freeze();
910
911 assert_eq!(bools.true_count(), 2);
912 assert!(bools.value(0));
913 assert!(bools.value(9));
914 }
915
916 #[test]
917 fn append_false_after_truncate_reads_back_false() {
918 let mut bools = BitBufferMut::new_set(16);
921 bools.truncate(12);
922 bools.append_false();
923 bools.append_true();
924
925 let bools = bools.freeze();
926 assert_eq!(bools.len(), 14);
927 assert!(
928 !bools.value(12),
929 "appended false must read back false after truncate"
930 );
931 assert!(bools.value(13));
932 }
933
934 #[test]
935 fn test_reserve_ensures_len_plus_additional() {
936 let mut bits = BitBufferMut::with_capacity(10);
940 assert_eq!(bits.len(), 0);
941
942 bits.reserve(100);
943
944 assert!(bits.capacity() >= 100);
946
947 bits.append_n(true, 50);
948 assert_eq!(bits.len(), 50);
949
950 bits.reserve(100);
951
952 assert!(bits.capacity() >= 150);
954 }
955
956 #[test]
957 fn test_with_offset_zero() {
958 let buf = BufferMut::zeroed(2);
960 let mut bit_buf = BitBufferMut::from_buffer(buf, 0, 16);
961
962 bit_buf.set(0);
964 bit_buf.set(7);
965 bit_buf.set(8);
966 bit_buf.set(15);
967
968 assert!(bit_buf.value(0));
970 assert!(bit_buf.value(7));
971 assert!(bit_buf.value(8));
972 assert!(bit_buf.value(15));
973 assert!(!bit_buf.value(1));
974 assert!(!bit_buf.value(9));
975
976 assert_eq!(bit_buf.as_slice()[0], 0b10000001);
978 assert_eq!(bit_buf.as_slice()[1], 0b10000001);
979 }
980
981 #[test]
982 fn test_with_offset_within_byte() {
983 let buf = buffer_mut![0b11111111, 0b00000000, 0b00000000];
985 let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 10);
986
987 assert!(bit_buf.value(0)); assert!(bit_buf.value(4)); assert!(!bit_buf.value(5)); bit_buf.set(7);
995 assert!(bit_buf.value(7));
996
997 bit_buf.unset(0);
999 assert!(!bit_buf.value(0));
1000 }
1001
1002 #[test]
1003 fn test_with_offset_byte_boundary() {
1004 let buf = buffer_mut![0xFF, 0x00, 0xFF];
1006 let mut bit_buf = BitBufferMut::from_buffer(buf, 8, 16);
1007
1008 for i in 0..8 {
1010 assert!(!bit_buf.value(i));
1011 }
1012 for i in 8..16 {
1014 assert!(bit_buf.value(i));
1015 }
1016
1017 bit_buf.set(0);
1019 bit_buf.set(3);
1020 assert!(bit_buf.value(0));
1021 assert!(bit_buf.value(3));
1022 }
1023
1024 #[test]
1025 fn test_with_large_offset() {
1026 let buf = buffer_mut![0xFF, 0xFF, 0xFF, 0xFF];
1028 let mut bit_buf = BitBufferMut::from_buffer(buf, 13, 10);
1029
1030 for i in 0..10 {
1032 assert!(bit_buf.value(i));
1033 }
1034
1035 bit_buf.unset(0);
1037 bit_buf.unset(5);
1038 bit_buf.unset(9);
1039
1040 assert!(!bit_buf.value(0));
1041 assert!(bit_buf.value(1));
1042 assert!(!bit_buf.value(5));
1043 assert!(!bit_buf.value(9));
1044 }
1045
1046 #[test]
1047 fn test_append_with_offset() {
1048 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);
1058 assert!(!bit_buf.value(0));
1059 assert!(bit_buf.value(1));
1060 assert!(bit_buf.value(2));
1061 }
1062
1063 #[test]
1064 fn test_append_n_with_offset_crossing_boundary() {
1065 let buf = BufferMut::zeroed(4);
1067 let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1068
1069 bit_buf.append_n(true, 10); assert_eq!(bit_buf.len(), 10);
1073 for i in 0..10 {
1074 assert!(bit_buf.value(i));
1075 }
1076
1077 assert_eq!(bit_buf.as_slice()[0], 0b11100000);
1081 assert_eq!(bit_buf.as_slice()[1], 0b01111111);
1082 }
1083
1084 #[test]
1085 fn test_truncate_with_offset() {
1086 let buf = buffer_mut![0xFF, 0xFF];
1087 let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 12);
1088
1089 assert_eq!(bit_buf.len(), 12);
1090
1091 bit_buf.truncate(8);
1093 assert_eq!(bit_buf.len(), 8);
1094
1095 bit_buf.truncate(3);
1097 assert_eq!(bit_buf.len(), 3);
1098
1099 bit_buf.truncate(10);
1101 assert_eq!(bit_buf.len(), 3);
1102 }
1103
1104 #[test]
1105 fn test_capacity_with_offset() {
1106 let buf = buffer_mut![0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; let bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1109
1110 assert!(bit_buf.capacity() >= 75);
1113 assert_eq!(bit_buf.capacity() % 8, (80 - 5) % 8);
1115 }
1116
1117 #[test]
1118 fn test_reserve_with_offset() {
1119 let buf = buffer_mut![0, 0]; let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
1122
1123 let initial_capacity = bit_buf.capacity();
1125 assert!(initial_capacity >= 13);
1126
1127 bit_buf.reserve(20);
1129
1130 assert!(bit_buf.capacity() >= 20);
1132 }
1133
1134 #[test]
1135 fn test_freeze_with_offset() {
1136 let buf = buffer_mut![0b11110000, 0b00001111];
1137 let mut bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
1138
1139 bit_buf.set(0);
1141 bit_buf.set(7);
1142
1143 let frozen = bit_buf.freeze();
1145 assert_eq!(frozen.offset(), 4);
1146 assert_eq!(frozen.len(), 8);
1147
1148 assert!(frozen.value(0));
1150 assert!(frozen.value(7));
1151 }
1152
1153 #[cfg_attr(miri, ignore)] #[test]
1155 fn append_after_clear_reads_back_false() {
1156 let mut bools = BitBufferMut::new_set(16);
1159 bools.clear();
1160 bools.append_false();
1161 bools.append_buffer(&crate::BitBuffer::new_unset(8));
1162
1163 let bools = bools.freeze();
1164 assert_eq!(bools.len(), 9);
1165 assert_eq!(bools.true_count(), 0);
1166 }
1167
1168 #[cfg_attr(miri, ignore)] #[test]
1170 fn test_append_buffer_after_truncate() {
1171 let mut buf = BitBufferMut::new_set(16);
1174 buf.truncate(3);
1175 buf.append_buffer(&crate::BitBuffer::new_unset(8));
1176
1177 let frozen = buf.freeze();
1178 assert_eq!(frozen.len(), 11);
1179 for i in 0..3 {
1180 assert!(frozen.value(i), "bit {i} should be set");
1181 }
1182 for i in 3..11 {
1183 assert!(!frozen.value(i), "bit {i} should be unset");
1184 }
1185 }
1186
1187 #[rstest]
1188 #[case::both_aligned(0, 0)]
1189 #[case::dst_unaligned(3, 0)]
1190 #[case::src_unaligned(0, 5)]
1191 #[case::mismatched(3, 5)]
1192 #[case::equal_nonzero(5, 5)]
1193 #[cfg_attr(miri, ignore)] fn test_append_buffer_long(#[case] dst_prefix: usize, #[case] src_start: usize) {
1195 let source = crate::BitBuffer::from_iter((0..301).map(|i| i % 3 == 0));
1197 let source = source.slice(src_start..301);
1198
1199 let mut dest = BitBufferMut::with_capacity(512);
1200 dest.append_n(true, dst_prefix);
1201 dest.append_buffer(&source);
1202
1203 assert_eq!(dest.len(), dst_prefix + source.len());
1204 for i in 0..dst_prefix {
1205 assert!(dest.value(i), "prefix bit {i}");
1206 }
1207 for i in 0..source.len() {
1208 assert_eq!(dest.value(dst_prefix + i), source.value(i), "bit {i}");
1209 }
1210 }
1211
1212 #[cfg_attr(miri, ignore)] #[test]
1214 fn test_append_buffer_with_offsets() {
1215 let source = bitbuffer![false, false, true, true, false, true];
1217
1218 let buf = BufferMut::zeroed(4);
1220 let mut dest = BitBufferMut::from_buffer(buf, 3, 0);
1221
1222 dest.append(true);
1224 dest.append(false);
1225
1226 dest.append_buffer(&source);
1228
1229 assert_eq!(dest.len(), 8);
1230 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)); }
1239
1240 #[test]
1241 fn test_set_unset_unchecked_with_offset() {
1242 let buf = BufferMut::zeroed(3);
1243 let mut bit_buf = BitBufferMut::from_buffer(buf, 7, 10);
1244
1245 unsafe {
1246 bit_buf.set_unchecked(0);
1247 bit_buf.set_unchecked(5);
1248 bit_buf.set_unchecked(9);
1249 }
1250
1251 assert!(bit_buf.value(0));
1252 assert!(bit_buf.value(5));
1253 assert!(bit_buf.value(9));
1254
1255 unsafe {
1256 bit_buf.unset_unchecked(5);
1257 }
1258
1259 assert!(!bit_buf.value(5));
1260 }
1261
1262 #[test]
1263 fn test_value_unchecked_with_offset() {
1264 let buf = buffer_mut![0b11110000, 0b00001111];
1265 let bit_buf = BitBufferMut::from_buffer(buf, 4, 8);
1266
1267 unsafe {
1268 assert!(bit_buf.value_unchecked(0));
1270 assert!(bit_buf.value_unchecked(3));
1271
1272 assert!(bit_buf.value_unchecked(4));
1274 assert!(bit_buf.value_unchecked(7));
1275 }
1276 }
1277
1278 #[test]
1279 fn test_append_alternating_with_offset() {
1280 let buf = BufferMut::zeroed(4);
1281 let mut bit_buf = BitBufferMut::from_buffer(buf, 2, 0);
1282
1283 for i in 0..20 {
1285 bit_buf.append(i % 2 == 0);
1286 }
1287
1288 assert_eq!(bit_buf.len(), 20);
1289 for i in 0..20 {
1290 assert_eq!(bit_buf.value(i), i % 2 == 0);
1291 }
1292 }
1293
1294 #[test]
1295 fn test_new_set_new_unset() {
1296 let set_buf = bitbuffer_mut![true; 10];
1297 let unset_buf = bitbuffer_mut![false; 10];
1298
1299 for i in 0..10 {
1300 assert!(set_buf.value(i));
1301 assert!(!unset_buf.value(i));
1302 }
1303
1304 assert_eq!(set_buf.len(), 10);
1305 assert_eq!(unset_buf.len(), 10);
1306 }
1307
1308 #[test]
1309 fn test_append_n_false_with_offset() {
1310 let buf = BufferMut::zeroed(4);
1311 let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1312
1313 bit_buf.append_n(false, 15);
1314
1315 assert_eq!(bit_buf.len(), 15);
1316 for i in 0..15 {
1317 assert!(!bit_buf.value(i));
1318 }
1319 }
1320
1321 #[test]
1322 fn test_append_n_true_with_offset() {
1323 let buf = BufferMut::zeroed(4);
1324 let mut bit_buf = BitBufferMut::from_buffer(buf, 5, 0);
1325
1326 bit_buf.append_n(true, 15);
1327
1328 assert_eq!(bit_buf.len(), 15);
1329 for i in 0..15 {
1330 assert!(bit_buf.value(i));
1331 }
1332 }
1333
1334 #[test]
1335 fn test_mixed_operations_with_offset() {
1336 let buf = BufferMut::zeroed(5);
1338 let mut bit_buf = BitBufferMut::from_buffer(buf, 3, 0);
1339
1340 bit_buf.append_n(true, 5);
1342 bit_buf.append_n(false, 3);
1343 bit_buf.append(true);
1344
1345 assert_eq!(bit_buf.len(), 9);
1346
1347 bit_buf.set(6); bit_buf.unset(2); assert!(bit_buf.value(0));
1353 assert!(bit_buf.value(1));
1354 assert!(!bit_buf.value(2)); assert!(bit_buf.value(3));
1356 assert!(bit_buf.value(4));
1357 assert!(!bit_buf.value(5));
1358 assert!(bit_buf.value(6)); assert!(!bit_buf.value(7));
1360 assert!(bit_buf.value(8));
1361
1362 bit_buf.truncate(6);
1364 assert_eq!(bit_buf.len(), 6);
1365
1366 let frozen = bit_buf.freeze();
1368 assert_eq!(frozen.offset(), 3);
1369 assert_eq!(frozen.len(), 6);
1370 }
1371
1372 #[test]
1373 fn test_from_iterator_with_incorrect_size_hint() {
1374 struct LyingIterator {
1381 values: Vec<bool>,
1382 index: usize,
1383 }
1384
1385 impl Iterator for LyingIterator {
1386 type Item = bool;
1387
1388 fn next(&mut self) -> Option<Self::Item> {
1389 (self.index < self.values.len()).then(|| {
1390 let val = self.values[self.index];
1391 self.index += 1;
1392 val
1393 })
1394 }
1395
1396 fn size_hint(&self) -> (usize, Option<usize>) {
1397 let remaining = self.values.len() - self.index;
1400 let lower = remaining.min(5); let upper = Some(5); (lower, upper)
1403 }
1404 }
1405
1406 let lying_iter = LyingIterator {
1408 values: vec![
1409 true, false, true, false, true, false, true, false, true, false,
1410 ],
1411 index: 0,
1412 };
1413
1414 let bit_buf: BitBufferMut = lying_iter.collect();
1417
1418 assert_eq!(bit_buf.len(), 10);
1420 for i in 0..10 {
1421 assert_eq!(bit_buf.value(i), i % 2 == 0);
1422 }
1423 }
1424
1425 #[rstest]
1429 #[case(0, 8)]
1430 #[case(1, 7)]
1431 #[case(7, 1)]
1432 #[case(8, 0)]
1433 fn from_buffer_accepts_offset_plus_len_within_the_buffer(
1434 #[case] offset: usize,
1435 #[case] len: usize,
1436 ) {
1437 let bits = BitBufferMut::from_buffer(buffer_mut![0u8; 1], offset, len);
1438 assert_eq!(bits.len(), len);
1439 }
1440
1441 #[rstest]
1442 #[case::offset_pushes_past_the_end(1, 8)]
1443 #[case::offset_alone_past_the_end(9, 0)]
1444 #[case::len_alone_past_the_end(0, 9)]
1445 #[should_panic(expected = "is too short for offset")]
1446 fn from_buffer_rejects_offset_plus_len_past_the_buffer(
1447 #[case] offset: usize,
1448 #[case] len: usize,
1449 ) {
1450 BitBufferMut::from_buffer(buffer_mut![0u8; 1], offset, len);
1451 }
1452
1453 #[test]
1456 fn from_buffer_allows_offsets_beyond_one_byte() {
1457 let bits = BitBufferMut::from_buffer(buffer_mut![0u8; 128], 1000, 24);
1458 assert_eq!(bits.len(), 24);
1459 }
1460
1461 #[test]
1463 #[should_panic(expected = "is too short for offset")]
1464 fn from_buffer_does_not_wrap_on_a_huge_offset() {
1465 BitBufferMut::from_buffer(buffer_mut![0u8; 1], usize::MAX, 8);
1466 }
1467}