1use crate::bit_chunk_iterator::BitChunks;
21
22#[inline]
28pub fn round_upto_multiple_of_64(num: usize) -> usize {
29 num.checked_next_multiple_of(64)
30 .expect("failed to round upto multiple of 64")
31}
32
33pub fn round_upto_power_of_2(num: usize, factor: usize) -> usize {
40 debug_assert!(factor > 0 && factor.is_power_of_two());
41 num.checked_add(factor - 1)
42 .expect("failed to round to next highest power of 2")
43 & !(factor - 1)
44}
45
46#[inline]
52pub fn get_bit(data: &[u8], i: usize) -> bool {
53 data[i / 8] & (1 << (i % 8)) != 0
54}
55
56#[inline]
63pub unsafe fn get_bit_raw(data: *const u8, i: usize) -> bool {
64 unsafe { (*data.add(i / 8) & (1 << (i % 8))) != 0 }
65}
66
67#[inline]
73pub fn set_bit(data: &mut [u8], i: usize) {
74 data[i / 8] |= 1 << (i % 8);
75}
76
77#[inline]
84pub unsafe fn set_bit_raw(data: *mut u8, i: usize) {
85 unsafe {
86 *data.add(i / 8) |= 1 << (i % 8);
87 }
88}
89
90#[inline]
96pub fn unset_bit(data: &mut [u8], i: usize) {
97 data[i / 8] &= !(1 << (i % 8));
98}
99
100#[inline]
107pub unsafe fn unset_bit_raw(data: *mut u8, i: usize) {
108 unsafe {
109 *data.add(i / 8) &= !(1 << (i % 8));
110 }
111}
112
113#[inline]
115pub fn ceil(value: usize, divisor: usize) -> usize {
116 value.div_ceil(divisor)
117}
118
119#[inline]
121pub(crate) fn read_u64(input: &[u8]) -> u64 {
122 let len = input.len().min(8);
123 let mut buf = [0_u8; 8];
124 buf[..len].copy_from_slice(input);
125 u64::from_le_bytes(buf)
126}
127
128#[inline]
146pub(crate) fn read_up_to_byte_from_offset(
147 slice: &[u8],
148 number_of_bits_to_read: usize,
149 bit_offset: usize,
150) -> u8 {
151 assert!(number_of_bits_to_read < 8, "can read up to 8 bits only");
152 assert!(bit_offset < 8, "bit offset must be less than 8");
153 assert_ne!(
154 number_of_bits_to_read, 0,
155 "number of bits to read must be greater than 0"
156 );
157 assert_ne!(slice.len(), 0, "slice must not be empty");
158
159 let number_of_bytes_to_read = ceil(number_of_bits_to_read + bit_offset, 8);
160
161 assert!(slice.len() >= number_of_bytes_to_read, "slice is too small");
163
164 let mut bits = slice[0] >> bit_offset;
165 for (i, &byte) in slice
166 .iter()
167 .take(number_of_bytes_to_read)
168 .enumerate()
169 .skip(1)
170 {
171 bits |= byte << (i * 8 - bit_offset);
172 }
173
174 bits & ((1 << number_of_bits_to_read) - 1)
175}
176
177pub fn apply_bitwise_binary_op<F>(
224 left: &mut [u8],
225 left_offset_in_bits: usize,
226 right: impl AsRef<[u8]>,
227 right_offset_in_bits: usize,
228 len_in_bits: usize,
229 mut op: F,
230) where
231 F: FnMut(u64, u64) -> u64,
232{
233 if len_in_bits == 0 {
234 return;
235 }
236
237 let bit_offset = left_offset_in_bits % 8;
239
240 let is_mutable_buffer_byte_aligned = bit_offset == 0;
241
242 if is_mutable_buffer_byte_aligned {
243 byte_aligned_bitwise_bin_op_helper(
244 left,
245 left_offset_in_bits,
246 right,
247 right_offset_in_bits,
248 len_in_bits,
249 op,
250 );
251 } else {
252 let bits_to_next_byte = (8 - bit_offset)
254 .min(len_in_bits);
257
258 {
259 let right_byte_offset = right_offset_in_bits / 8;
260
261 let right_first_byte = crate::util::bit_util::read_up_to_byte_from_offset(
263 &right.as_ref()[right_byte_offset..],
264 bits_to_next_byte,
265 right_offset_in_bits % 8,
267 );
268
269 align_to_byte(
270 left,
271 &mut |left| op(left, right_first_byte as u64),
273 left_offset_in_bits,
274 bits_to_next_byte,
275 );
276 }
277
278 let offset_in_bits = left_offset_in_bits + bits_to_next_byte;
279 let right_offset_in_bits = right_offset_in_bits + bits_to_next_byte;
280 let len_in_bits = len_in_bits.saturating_sub(bits_to_next_byte);
281
282 if len_in_bits == 0 {
283 return;
284 }
285
286 byte_aligned_bitwise_bin_op_helper(
288 left,
289 offset_in_bits,
290 right,
291 right_offset_in_bits,
292 len_in_bits,
293 op,
294 );
295 }
296}
297
298pub fn apply_bitwise_unary_op<F>(
338 buffer: &mut [u8],
339 offset_in_bits: usize,
340 len_in_bits: usize,
341 mut op: F,
342) where
343 F: FnMut(u64) -> u64,
344{
345 if len_in_bits == 0 {
346 return;
347 }
348
349 let left_bit_offset = offset_in_bits % 8;
351
352 let is_mutable_buffer_byte_aligned = left_bit_offset == 0;
353
354 if is_mutable_buffer_byte_aligned {
355 byte_aligned_bitwise_unary_op_helper(buffer, offset_in_bits, len_in_bits, op);
356 } else {
357 align_to_byte(buffer, &mut op, offset_in_bits, len_in_bits);
358
359 let bits_to_next_byte = 8 - left_bit_offset;
361
362 let offset_in_bits = offset_in_bits + bits_to_next_byte;
363 let len_in_bits = len_in_bits.saturating_sub(bits_to_next_byte);
364
365 if len_in_bits == 0 {
366 return;
367 }
368
369 byte_aligned_bitwise_unary_op_helper(buffer, offset_in_bits, len_in_bits, op);
371 }
372}
373
374#[inline]
388fn byte_aligned_bitwise_bin_op_helper<F>(
389 left: &mut [u8],
390 left_offset_in_bits: usize,
391 right: impl AsRef<[u8]>,
392 right_offset_in_bits: usize,
393 len_in_bits: usize,
394 mut op: F,
395) where
396 F: FnMut(u64, u64) -> u64,
397{
398 assert_eq!(
400 left_offset_in_bits % 8,
401 0,
402 "offset_in_bits must be byte aligned"
403 );
404
405 let (complete_u64_chunks, remainder_bytes) =
407 U64UnalignedSlice::split(left, left_offset_in_bits, len_in_bits);
408
409 let right_chunks = BitChunks::new(right.as_ref(), right_offset_in_bits, len_in_bits);
410 assert_eq!(
411 self::ceil(right_chunks.remainder_len(), 8),
412 remainder_bytes.len()
413 );
414
415 let right_chunks_iter = right_chunks.iter();
416 assert_eq!(right_chunks_iter.len(), complete_u64_chunks.len());
417
418 complete_u64_chunks.zip_modify(right_chunks_iter, &mut op);
420
421 if right_chunks.remainder_len() > 0 {
423 handle_mutable_buffer_remainder(
424 &mut op,
425 remainder_bytes,
426 right_chunks.remainder_bits(),
427 right_chunks.remainder_len(),
428 )
429 }
430}
431
432#[inline]
444fn byte_aligned_bitwise_unary_op_helper<F>(
445 buffer: &mut [u8],
446 offset_in_bits: usize,
447 len_in_bits: usize,
448 mut op: F,
449) where
450 F: FnMut(u64) -> u64,
451{
452 assert_eq!(offset_in_bits % 8, 0, "offset_in_bits must be byte aligned");
454
455 let remainder_len = len_in_bits % 64;
456
457 let (complete_u64_chunks, remainder_bytes) =
458 U64UnalignedSlice::split(buffer, offset_in_bits, len_in_bits);
459
460 assert_eq!(self::ceil(remainder_len, 8), remainder_bytes.len());
461
462 complete_u64_chunks.apply_unary_op(&mut op);
464
465 if remainder_len > 0 {
467 handle_mutable_buffer_remainder_unary(&mut op, remainder_bytes, remainder_len)
468 }
469}
470
471fn align_to_byte<F>(
485 buffer: &mut [u8],
486 op: &mut F,
487 offset_in_bits: usize,
488 remaining_len_in_bits: usize,
489) where
490 F: FnMut(u64) -> u64,
491{
492 let byte_offset = offset_in_bits / 8;
493 let bit_offset = offset_in_bits % 8;
494
495 debug_assert_ne!(bit_offset, 0, "offset_in_bits must not be byte aligned");
497
498 let first_byte: u8 = buffer[byte_offset];
500
501 let relevant_first_byte = first_byte >> bit_offset;
503
504 let result_first_byte = op(relevant_first_byte as u64) as u8;
506
507 let result_first_byte = result_first_byte << bit_offset;
509
510 let bits_in_this_byte = (8 - bit_offset).min(remaining_len_in_bits);
517 let write_mask = ((1u8 << bits_in_this_byte) - 1) << bit_offset;
518
519 let result_first_byte = (first_byte & !write_mask) | (result_first_byte & write_mask);
520
521 buffer[byte_offset] = result_first_byte;
523}
524
525struct U64UnalignedSlice<'a> {
537 ptr: *mut u64,
541
542 len: usize,
544
545 _marker: std::marker::PhantomData<&'a u8>,
547}
548
549impl<'a> U64UnalignedSlice<'a> {
550 fn split(
555 buffer: &'a mut [u8],
556 offset_in_bits: usize,
557 len_in_bits: usize,
558 ) -> (Self, &'a mut [u8]) {
559 let left_buffer_mut: &mut [u8] = {
561 let last_offset = self::ceil(offset_in_bits + len_in_bits, 8);
562 assert!(last_offset <= buffer.len());
563
564 let byte_offset = offset_in_bits / 8;
565
566 &mut buffer[byte_offset..last_offset]
567 };
568
569 let number_of_u64_we_can_fit = len_in_bits / (u64::BITS as usize);
570
571 let u64_len_in_bytes = number_of_u64_we_can_fit * size_of::<u64>();
573
574 assert!(u64_len_in_bytes <= left_buffer_mut.len());
575 let (bytes_for_u64, remainder) = left_buffer_mut.split_at_mut(u64_len_in_bytes);
576
577 #[expect(
578 clippy::cast_ptr_alignment,
579 reason = "`U64UnalignedSlice` only reads and writes through the unaligned methods"
580 )]
581 let ptr = bytes_for_u64.as_mut_ptr().cast::<u64>();
582
583 let this = Self {
584 ptr,
585 len: number_of_u64_we_can_fit,
586 _marker: std::marker::PhantomData,
587 };
588
589 (this, remainder)
590 }
591
592 fn len(&self) -> usize {
593 self.len
594 }
595
596 fn zip_modify(
599 mut self,
600 mut zip_iter: impl ExactSizeIterator<Item = u64>,
601 mut map: impl FnMut(u64, u64) -> u64,
602 ) {
603 assert_eq!(self.len, zip_iter.len());
604
605 if let Some(right) = zip_iter.next() {
610 unsafe {
613 self.apply_bin_op(right, &mut map);
614 }
615
616 }
618
619 for right in zip_iter {
620 self.ptr = unsafe { self.ptr.add(1) };
624
625 unsafe {
627 self.apply_bin_op(right, &mut map);
628 }
629
630 }
632 }
633
634 #[inline]
640 unsafe fn apply_bin_op(&mut self, right: u64, mut map: impl FnMut(u64, u64) -> u64) {
641 let current_input = unsafe {
644 self.ptr
645 .read_unaligned()
647 .to_le()
650 };
651
652 let combined = map(current_input, right);
653
654 unsafe { self.ptr.write_unaligned(combined) }
659 }
660
661 fn apply_unary_op(mut self, mut map: impl FnMut(u64) -> u64) {
663 if self.len == 0 {
664 return;
665 }
666
667 unsafe {
674 self.apply_bin_op(0, &mut |left, _| map(left));
676
677 }
679
680 for _ in 1..self.len {
681 self.ptr = unsafe { self.ptr.add(1) };
685
686 unsafe {
688 self.apply_bin_op(0, &mut |left, _| map(left));
690 }
691
692 }
694 }
695}
696
697#[inline]
710fn handle_mutable_buffer_remainder<F>(
711 op: &mut F,
712 start_remainder_mut_slice: &mut [u8],
713 right_remainder_bits: u64,
714 remainder_len: usize,
715) where
716 F: FnMut(u64, u64) -> u64,
717{
718 let left_remainder_bits = get_remainder_bits(start_remainder_mut_slice, remainder_len);
720
721 let rem = op(left_remainder_bits, right_remainder_bits);
723
724 set_remainder_bits(start_remainder_mut_slice, rem, remainder_len);
726}
727
728#[inline]
740fn set_remainder_bits(start_remainder_mut_slice: &mut [u8], rem: u64, remainder_len: usize) {
741 assert_ne!(
742 start_remainder_mut_slice.len(),
743 0,
744 "start_remainder_mut_slice must not be empty"
745 );
746 assert!(remainder_len < 64, "remainder_len must be less than 64");
747
748 assert_eq!(
751 start_remainder_mut_slice.len(),
752 self::ceil(remainder_len, 8),
753 "start_remainder_mut_slice length must be equal to ceil(remainder_len, 8)"
754 );
755
756 let rem = {
762 let current = start_remainder_mut_slice
767 .last()
768 .unwrap();
770
771 let current = (*current as u64) << ((start_remainder_mut_slice.len() - 1) * 8);
774
775 let inside_remainder_mask = (1 << remainder_len) - 1;
778 let outside_remainder_mask = !inside_remainder_mask;
781
782 let current = current & outside_remainder_mask;
784
785 let rem = rem & inside_remainder_mask;
787
788 current | rem
790 };
791
792 {
794 let remainder_bytes = start_remainder_mut_slice.len();
795
796 let rem = &rem.to_le_bytes()[0..remainder_bytes];
798
799 let src = rem.as_ptr();
803 unsafe {
807 std::ptr::copy_nonoverlapping(
808 src,
809 start_remainder_mut_slice.as_mut_ptr(),
810 remainder_bytes,
811 )
812 };
813 }
814}
815
816#[inline]
829fn get_remainder_bits(remainder: &[u8], remainder_len: usize) -> u64 {
830 assert!(remainder.len() < 64, "remainder_len must be less than 64");
831 assert_eq!(
832 remainder.len(),
833 self::ceil(remainder_len, 8),
834 "remainder and remainder len ceil must be the same"
835 );
836
837 let bits = remainder
838 .iter()
839 .enumerate()
840 .fold(0_u64, |acc, (index, &byte)| {
841 acc | ((byte as u64) << (index * 8))
842 });
843
844 bits & ((1 << remainder_len) - 1)
845}
846
847#[inline]
858fn handle_mutable_buffer_remainder_unary<F>(
859 op: &mut F,
860 start_remainder_mut: &mut [u8],
861 remainder_len: usize,
862) where
863 F: FnMut(u64) -> u64,
864{
865 let left_remainder_bits = get_remainder_bits(start_remainder_mut, remainder_len);
867
868 let rem = op(left_remainder_bits);
870
871 set_remainder_bits(start_remainder_mut, rem, remainder_len);
873}
874
875#[cfg(test)]
876mod tests {
877 use std::collections::HashSet;
878
879 use super::*;
880 use crate::bit_iterator::BitIterator;
881 use crate::{BooleanBuffer, BooleanBufferBuilder, MutableBuffer};
882 use rand::rngs::StdRng;
883 use rand::{RngExt, SeedableRng};
884
885 #[test]
886 fn test_round_upto_multiple_of_64() {
887 assert_eq!(0, round_upto_multiple_of_64(0));
888 assert_eq!(64, round_upto_multiple_of_64(1));
889 assert_eq!(64, round_upto_multiple_of_64(63));
890 assert_eq!(64, round_upto_multiple_of_64(64));
891 assert_eq!(128, round_upto_multiple_of_64(65));
892 assert_eq!(192, round_upto_multiple_of_64(129));
893 }
894
895 #[test]
896 #[should_panic(expected = "failed to round upto multiple of 64")]
897 fn test_round_upto_multiple_of_64_panic() {
898 let _ = round_upto_multiple_of_64(usize::MAX);
899 }
900
901 #[test]
902 #[should_panic(expected = "failed to round to next highest power of 2")]
903 fn test_round_upto_panic() {
904 let _ = round_upto_power_of_2(usize::MAX, 2);
905 }
906
907 #[test]
908 fn test_get_bit() {
909 assert!(get_bit(&[0b00001101], 0));
911 assert!(!get_bit(&[0b00001101], 1));
912 assert!(get_bit(&[0b00001101], 2));
913 assert!(get_bit(&[0b00001101], 3));
914
915 assert!(get_bit(&[0b01001001, 0b01010010], 0));
917 assert!(!get_bit(&[0b01001001, 0b01010010], 1));
918 assert!(!get_bit(&[0b01001001, 0b01010010], 2));
919 assert!(get_bit(&[0b01001001, 0b01010010], 3));
920 assert!(!get_bit(&[0b01001001, 0b01010010], 4));
921 assert!(!get_bit(&[0b01001001, 0b01010010], 5));
922 assert!(get_bit(&[0b01001001, 0b01010010], 6));
923 assert!(!get_bit(&[0b01001001, 0b01010010], 7));
924 assert!(!get_bit(&[0b01001001, 0b01010010], 8));
925 assert!(get_bit(&[0b01001001, 0b01010010], 9));
926 assert!(!get_bit(&[0b01001001, 0b01010010], 10));
927 assert!(!get_bit(&[0b01001001, 0b01010010], 11));
928 assert!(get_bit(&[0b01001001, 0b01010010], 12));
929 assert!(!get_bit(&[0b01001001, 0b01010010], 13));
930 assert!(get_bit(&[0b01001001, 0b01010010], 14));
931 assert!(!get_bit(&[0b01001001, 0b01010010], 15));
932 }
933
934 pub fn seedable_rng() -> StdRng {
935 StdRng::seed_from_u64(42)
936 }
937
938 #[test]
939 fn test_get_bit_raw() {
940 const NUM_BYTE: usize = 10;
941 let mut buf = [0; NUM_BYTE];
942 let mut expected = vec![];
943 let mut rng = seedable_rng();
944 for i in 0..8 * NUM_BYTE {
945 let b = rng.random_bool(0.5);
946 expected.push(b);
947 if b {
948 set_bit(&mut buf[..], i)
949 }
950 }
951
952 let raw_ptr = buf.as_ptr();
953 for (i, b) in expected.iter().enumerate() {
954 unsafe {
955 assert_eq!(*b, get_bit_raw(raw_ptr, i));
956 }
957 }
958 }
959
960 #[test]
961 fn test_set_bit() {
962 let mut b = [0b00000010];
963 set_bit(&mut b, 0);
964 assert_eq!([0b00000011], b);
965 set_bit(&mut b, 1);
966 assert_eq!([0b00000011], b);
967 set_bit(&mut b, 7);
968 assert_eq!([0b10000011], b);
969 }
970
971 #[test]
972 fn test_unset_bit() {
973 let mut b = [0b11111101];
974 unset_bit(&mut b, 0);
975 assert_eq!([0b11111100], b);
976 unset_bit(&mut b, 1);
977 assert_eq!([0b11111100], b);
978 unset_bit(&mut b, 7);
979 assert_eq!([0b01111100], b);
980 }
981
982 #[test]
983 fn test_set_bit_raw() {
984 const NUM_BYTE: usize = 10;
985 let mut buf = vec![0; NUM_BYTE];
986 let mut expected = vec![];
987 let mut rng = seedable_rng();
988 for i in 0..8 * NUM_BYTE {
989 let b = rng.random_bool(0.5);
990 expected.push(b);
991 if b {
992 unsafe {
993 set_bit_raw(buf.as_mut_ptr(), i);
994 }
995 }
996 }
997
998 let raw_ptr = buf.as_ptr();
999 for (i, b) in expected.iter().enumerate() {
1000 unsafe {
1001 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1002 }
1003 }
1004 }
1005
1006 #[test]
1007 fn test_unset_bit_raw() {
1008 const NUM_BYTE: usize = 10;
1009 let mut buf = vec![255; NUM_BYTE];
1010 let mut expected = vec![];
1011 let mut rng = seedable_rng();
1012 for i in 0..8 * NUM_BYTE {
1013 let b = rng.random_bool(0.5);
1014 expected.push(b);
1015 if !b {
1016 unsafe {
1017 unset_bit_raw(buf.as_mut_ptr(), i);
1018 }
1019 }
1020 }
1021
1022 let raw_ptr = buf.as_ptr();
1023 for (i, b) in expected.iter().enumerate() {
1024 unsafe {
1025 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1026 }
1027 }
1028 }
1029
1030 #[test]
1031 fn test_get_set_bit_roundtrip() {
1032 const NUM_BYTES: usize = 10;
1033 const NUM_SETS: usize = 10;
1034
1035 let mut buffer: [u8; NUM_BYTES * 8] = [0; NUM_BYTES * 8];
1036 let mut v = HashSet::new();
1037 let mut rng = seedable_rng();
1038 for _ in 0..NUM_SETS {
1039 let offset = rng.random_range(0..8 * NUM_BYTES);
1040 v.insert(offset);
1041 set_bit(&mut buffer[..], offset);
1042 }
1043 for i in 0..NUM_BYTES * 8 {
1044 assert_eq!(v.contains(&i), get_bit(&buffer[..], i));
1045 }
1046 }
1047
1048 #[test]
1049 fn test_ceil() {
1050 assert_eq!(ceil(0, 1), 0);
1051 assert_eq!(ceil(1, 1), 1);
1052 assert_eq!(ceil(1, 2), 1);
1053 assert_eq!(ceil(1, 8), 1);
1054 assert_eq!(ceil(7, 8), 1);
1055 assert_eq!(ceil(8, 8), 1);
1056 assert_eq!(ceil(9, 8), 2);
1057 assert_eq!(ceil(9, 9), 1);
1058 assert_eq!(ceil(10000000000, 10), 1000000000);
1059 assert_eq!(ceil(10, 10000000000), 1);
1060 assert_eq!(ceil(10000000000, 1000000000), 10);
1061 }
1062
1063 #[test]
1064 fn test_read_up_to() {
1065 let all_ones = &[0b10111001, 0b10001100];
1066
1067 for (bit_offset, expected) in [
1068 (0, 0b00000001),
1069 (1, 0b00000000),
1070 (2, 0b00000000),
1071 (3, 0b00000001),
1072 (4, 0b00000001),
1073 (5, 0b00000001),
1074 (6, 0b00000000),
1075 (7, 0b00000001),
1076 ] {
1077 let result = read_up_to_byte_from_offset(all_ones, 1, bit_offset);
1078 assert_eq!(
1079 result, expected,
1080 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1081 );
1082 }
1083
1084 for (bit_offset, expected) in [
1085 (0, 0b00000001),
1086 (1, 0b00000000),
1087 (2, 0b00000010),
1088 (3, 0b00000011),
1089 (4, 0b00000011),
1090 (5, 0b00000001),
1091 (6, 0b00000010),
1092 (7, 0b00000001),
1093 ] {
1094 let result = read_up_to_byte_from_offset(all_ones, 2, bit_offset);
1095 assert_eq!(
1096 result, expected,
1097 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1098 );
1099 }
1100
1101 for (bit_offset, expected) in [
1102 (0, 0b00111001),
1103 (1, 0b00011100),
1104 (2, 0b00101110),
1105 (3, 0b00010111),
1106 (4, 0b00001011),
1107 (5, 0b00100101),
1108 (6, 0b00110010),
1109 (7, 0b00011001),
1110 ] {
1111 let result = read_up_to_byte_from_offset(all_ones, 6, bit_offset);
1112 assert_eq!(
1113 result, expected,
1114 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1115 );
1116 }
1117
1118 for (bit_offset, expected) in [
1119 (0, 0b00111001),
1120 (1, 0b01011100),
1121 (2, 0b00101110),
1122 (3, 0b00010111),
1123 (4, 0b01001011),
1124 (5, 0b01100101),
1125 (6, 0b00110010),
1126 (7, 0b00011001),
1127 ] {
1128 let result = read_up_to_byte_from_offset(all_ones, 7, bit_offset);
1129 assert_eq!(
1130 result, expected,
1131 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1132 );
1133 }
1134 }
1135
1136 fn test_mutable_buffer_bin_op_helper<F, G>(
1139 left_data: &[bool],
1140 right_data: &[bool],
1141 left_offset_in_bits: usize,
1142 right_offset_in_bits: usize,
1143 len_in_bits: usize,
1144 op: F,
1145 mut expected_op: G,
1146 ) where
1147 F: FnMut(u64, u64) -> u64,
1148 G: FnMut(bool, bool) -> bool,
1149 {
1150 let mut left_buffer = BooleanBufferBuilder::new(len_in_bits);
1151 left_buffer.append_slice(left_data);
1152 let right_buffer = BooleanBuffer::from(right_data);
1153
1154 let expected: Vec<bool> = left_data
1155 .iter()
1156 .skip(left_offset_in_bits)
1157 .zip(right_data.iter().skip(right_offset_in_bits))
1158 .take(len_in_bits)
1159 .map(|(l, r)| expected_op(*l, *r))
1160 .collect();
1161
1162 let before = left_buffer.as_slice().to_vec();
1163
1164 apply_bitwise_binary_op(
1165 left_buffer.as_slice_mut(),
1166 left_offset_in_bits,
1167 right_buffer.inner(),
1168 right_offset_in_bits,
1169 len_in_bits,
1170 op,
1171 );
1172
1173 let result: Vec<bool> =
1174 BitIterator::new(left_buffer.as_slice(), left_offset_in_bits, len_in_bits).collect();
1175
1176 assert_eq!(
1177 result, expected,
1178 "Failed with left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1179 );
1180
1181 assert_bits_outside_range_preserved(
1182 &before,
1183 left_buffer.as_slice(),
1184 left_offset_in_bits,
1185 len_in_bits,
1186 &format!(
1187 "left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1188 ),
1189 );
1190 }
1191
1192 fn assert_bits_outside_range_preserved(
1195 before: &[u8],
1196 after: &[u8],
1197 offset_in_bits: usize,
1198 len_in_bits: usize,
1199 context: &str,
1200 ) {
1201 assert_eq!(before.len(), after.len());
1202 for i in 0..before.len() * 8 {
1203 if i >= offset_in_bits && i < offset_in_bits + len_in_bits {
1204 continue;
1205 }
1206 assert_eq!(
1207 get_bit(before, i),
1208 get_bit(after, i),
1209 "bit {i} outside the requested range was modified ({context})"
1210 );
1211 }
1212 }
1213
1214 fn test_mutable_buffer_unary_op_helper<F, G>(
1217 data: &[bool],
1218 offset_in_bits: usize,
1219 len_in_bits: usize,
1220 op: F,
1221 mut expected_op: G,
1222 ) where
1223 F: FnMut(u64) -> u64,
1224 G: FnMut(bool) -> bool,
1225 {
1226 let mut buffer = BooleanBufferBuilder::new(len_in_bits);
1227 buffer.append_slice(data);
1228
1229 let expected: Vec<bool> = data
1230 .iter()
1231 .skip(offset_in_bits)
1232 .take(len_in_bits)
1233 .map(|b| expected_op(*b))
1234 .collect();
1235
1236 let before = buffer.as_slice().to_vec();
1237
1238 apply_bitwise_unary_op(buffer.as_slice_mut(), offset_in_bits, len_in_bits, op);
1239
1240 let result: Vec<bool> =
1241 BitIterator::new(buffer.as_slice(), offset_in_bits, len_in_bits).collect();
1242
1243 assert_eq!(
1244 result, expected,
1245 "Failed with offset={offset_in_bits}, len={len_in_bits}"
1246 );
1247
1248 assert_bits_outside_range_preserved(
1249 &before,
1250 buffer.as_slice(),
1251 offset_in_bits,
1252 len_in_bits,
1253 &format!("offset={offset_in_bits}, len={len_in_bits}"),
1254 );
1255 }
1256
1257 fn create_test_data(len: usize) -> (Vec<bool>, Vec<bool>) {
1259 let mut rng = rand::rng();
1260 let left: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1261 let right: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1262 (left, right)
1263 }
1264
1265 fn test_all_binary_ops(
1267 left_data: &[bool],
1268 right_data: &[bool],
1269 left_offset_in_bits: usize,
1270 right_offset_in_bits: usize,
1271 len_in_bits: usize,
1272 ) {
1273 test_mutable_buffer_bin_op_helper(
1275 left_data,
1276 right_data,
1277 left_offset_in_bits,
1278 right_offset_in_bits,
1279 len_in_bits,
1280 |a, b| a & b,
1281 |a, b| a & b,
1282 );
1283
1284 test_mutable_buffer_bin_op_helper(
1286 left_data,
1287 right_data,
1288 left_offset_in_bits,
1289 right_offset_in_bits,
1290 len_in_bits,
1291 |a, b| a | b,
1292 |a, b| a | b,
1293 );
1294
1295 test_mutable_buffer_bin_op_helper(
1297 left_data,
1298 right_data,
1299 left_offset_in_bits,
1300 right_offset_in_bits,
1301 len_in_bits,
1302 |a, b| a ^ b,
1303 |a, b| a ^ b,
1304 );
1305 }
1306
1307 #[test]
1310 fn test_binary_ops_less_than_byte() {
1311 let (left, right) = create_test_data(4);
1312 test_all_binary_ops(&left, &right, 0, 0, 4);
1313 }
1314
1315 #[test]
1316 fn test_binary_ops_less_than_byte_across_boundary() {
1317 let (left, right) = create_test_data(16);
1318 test_all_binary_ops(&left, &right, 6, 6, 4);
1319 }
1320
1321 #[test]
1322 fn test_binary_ops_exactly_byte() {
1323 let (left, right) = create_test_data(16);
1324 test_all_binary_ops(&left, &right, 0, 0, 8);
1325 }
1326
1327 #[test]
1328 fn test_binary_ops_more_than_byte_less_than_u64() {
1329 let (left, right) = create_test_data(64);
1330 test_all_binary_ops(&left, &right, 0, 0, 32);
1331 }
1332
1333 #[test]
1334 fn test_binary_ops_exactly_u64() {
1335 let (left, right) = create_test_data(180);
1336 test_all_binary_ops(&left, &right, 0, 0, 64);
1337 test_all_binary_ops(&left, &right, 64, 9, 64);
1338 test_all_binary_ops(&left, &right, 8, 100, 64);
1339 test_all_binary_ops(&left, &right, 1, 15, 64);
1340 test_all_binary_ops(&left, &right, 12, 10, 64);
1341 test_all_binary_ops(&left, &right, 180 - 64, 2, 64);
1342 }
1343
1344 #[test]
1345 fn test_binary_ops_more_than_u64_not_multiple() {
1346 let (left, right) = create_test_data(200);
1347 test_all_binary_ops(&left, &right, 0, 0, 100);
1348 }
1349
1350 #[test]
1351 fn test_binary_ops_exactly_multiple_u64() {
1352 let (left, right) = create_test_data(256);
1353 test_all_binary_ops(&left, &right, 0, 0, 128);
1354 }
1355
1356 #[test]
1357 fn test_binary_ops_more_than_multiple_u64() {
1358 let (left, right) = create_test_data(300);
1359 test_all_binary_ops(&left, &right, 0, 0, 200);
1360 }
1361
1362 #[test]
1363 fn test_binary_ops_byte_aligned_no_remainder() {
1364 let (left, right) = create_test_data(200);
1365 test_all_binary_ops(&left, &right, 0, 0, 128);
1366 }
1367
1368 #[test]
1369 fn test_binary_ops_byte_aligned_with_remainder() {
1370 let (left, right) = create_test_data(200);
1371 test_all_binary_ops(&left, &right, 0, 0, 100);
1372 }
1373
1374 #[test]
1375 fn test_binary_ops_not_byte_aligned_no_remainder() {
1376 let (left, right) = create_test_data(200);
1377 test_all_binary_ops(&left, &right, 3, 3, 128);
1378 }
1379
1380 #[test]
1381 fn test_binary_ops_not_byte_aligned_with_remainder() {
1382 let (left, right) = create_test_data(200);
1383 test_all_binary_ops(&left, &right, 5, 5, 100);
1384 }
1385
1386 #[test]
1387 fn test_binary_ops_different_offsets() {
1388 let (left, right) = create_test_data(200);
1389 test_all_binary_ops(&left, &right, 3, 7, 50);
1390 }
1391
1392 #[test]
1393 fn test_binary_ops_offsets_greater_than_8_less_than_64() {
1394 let (left, right) = create_test_data(200);
1395 test_all_binary_ops(&left, &right, 13, 27, 100);
1396 }
1397
1398 #[test]
1401 fn test_not_less_than_byte() {
1402 let data = vec![true, false, true, false];
1403 test_mutable_buffer_unary_op_helper(&data, 0, 4, |a| !a, |a| !a);
1404 }
1405
1406 #[test]
1407 fn test_not_less_than_byte_across_boundary() {
1408 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1409 test_mutable_buffer_unary_op_helper(&data, 6, 4, |a| !a, |a| !a);
1410 }
1411
1412 #[test]
1413 fn test_not_exactly_byte() {
1414 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1415 test_mutable_buffer_unary_op_helper(&data, 0, 8, |a| !a, |a| !a);
1416 }
1417
1418 #[test]
1419 fn test_not_more_than_byte_less_than_u64() {
1420 let data: Vec<bool> = (0..64).map(|i| i % 2 == 0).collect();
1421 test_mutable_buffer_unary_op_helper(&data, 0, 32, |a| !a, |a| !a);
1422 }
1423
1424 #[test]
1425 fn test_not_exactly_u64() {
1426 let data: Vec<bool> = (0..128).map(|i| i % 2 == 0).collect();
1427 test_mutable_buffer_unary_op_helper(&data, 0, 64, |a| !a, |a| !a);
1428 }
1429
1430 #[test]
1431 fn test_not_more_than_u64_not_multiple() {
1432 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1433 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1434 }
1435
1436 #[test]
1437 fn test_not_exactly_multiple_u64() {
1438 let data: Vec<bool> = (0..256).map(|i| i % 2 == 0).collect();
1439 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1440 }
1441
1442 #[test]
1443 fn test_not_more_than_multiple_u64() {
1444 let data: Vec<bool> = (0..300).map(|i| i % 2 == 0).collect();
1445 test_mutable_buffer_unary_op_helper(&data, 0, 200, |a| !a, |a| !a);
1446 }
1447
1448 #[test]
1449 fn test_not_byte_aligned_no_remainder() {
1450 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1451 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1452 }
1453
1454 #[test]
1455 fn test_not_byte_aligned_with_remainder() {
1456 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1457 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1458 }
1459
1460 #[test]
1461 fn test_not_not_byte_aligned_no_remainder() {
1462 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1463 test_mutable_buffer_unary_op_helper(&data, 3, 128, |a| !a, |a| !a);
1464 }
1465
1466 #[test]
1467 fn test_not_not_byte_aligned_with_remainder() {
1468 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1469 test_mutable_buffer_unary_op_helper(&data, 5, 100, |a| !a, |a| !a);
1470 }
1471
1472 #[test]
1475 fn test_empty_length() {
1476 let (left, right) = create_test_data(16);
1477 test_all_binary_ops(&left, &right, 0, 0, 0);
1478 }
1479
1480 #[test]
1481 fn test_single_bit() {
1482 let (left, right) = create_test_data(16);
1483 test_all_binary_ops(&left, &right, 0, 0, 1);
1484 }
1485
1486 #[test]
1487 fn test_single_bit_at_offset() {
1488 let (left, right) = create_test_data(16);
1489 test_all_binary_ops(&left, &right, 7, 7, 1);
1490 }
1491
1492 #[test]
1493 fn test_not_single_bit() {
1494 let data = vec![true, false, true, false];
1495 test_mutable_buffer_unary_op_helper(&data, 0, 1, |a| !a, |a| !a);
1496 }
1497
1498 #[test]
1499 fn test_not_empty_length() {
1500 let data = vec![true, false, true, false];
1501 test_mutable_buffer_unary_op_helper(&data, 0, 0, |a| !a, |a| !a);
1502 }
1503
1504 #[test]
1505 fn test_less_than_byte_unaligned_and_not_enough_bits() {
1506 let left_offset_in_bits = 2;
1507 let right_offset_in_bits = 4;
1508 let len_in_bits = 1;
1509
1510 let right = (0..8).map(|i| (i / 2) % 2 == 0).collect::<Vec<_>>();
1512 let left = (0..3).map(|i| i % 2 == 0).collect::<Vec<_>>();
1514 test_all_binary_ops(
1515 &left,
1516 &right,
1517 left_offset_in_bits,
1518 right_offset_in_bits,
1519 len_in_bits,
1520 );
1521 }
1522
1523 #[test]
1526 fn test_ops_ending_inside_the_first_partial_byte() {
1527 let (left, right) = create_test_data(32);
1528 for offset in 1..8 {
1529 for len in 1..=(8 - offset) {
1531 test_all_binary_ops(&left, &right, offset, offset, len);
1532 test_all_binary_ops(&left, &right, offset, (offset + 3) % 8, len);
1533 test_mutable_buffer_unary_op_helper(&left, offset, len, |a| !a, |a| !a);
1534 }
1535 }
1536 }
1537
1538 #[test]
1539 fn test_and_within_first_partial_byte_preserves_trailing_bits() {
1540 let mut left = vec![0b11111111u8, 0b11111111u8];
1541 let right = vec![0b00000000u8, 0b00000000u8];
1542 apply_bitwise_binary_op(&mut left, 1, &right, 0, 1, |a, b| a & b);
1544 assert_eq!(left, vec![0b11111101u8, 0b11111111u8]);
1545 }
1546
1547 #[test]
1548 fn test_not_within_first_partial_byte_preserves_trailing_bits() {
1549 let mut buffer = vec![0b00000000u8];
1550 apply_bitwise_unary_op(&mut buffer, 3, 2, |a| !a);
1552 assert_eq!(buffer, vec![0b00011000u8]);
1553 }
1554
1555 #[test]
1559 fn test_or_with_multi_byte_remainder_preserves_boundary_bits() {
1560 let mut left = vec![0b00000000u8, 0b00000000u8, 0b11110000u8];
1561 let right = vec![0b11111111u8, 0b11111111u8, 0b11111111u8];
1562 apply_bitwise_binary_op(&mut left, 0, &right, 0, 20, |a, b| a | b);
1564 assert_eq!(
1565 left,
1566 vec![0b11111111u8, 0b11111111u8, 0b11111111u8],
1567 "the boundary byte lost its out-of-range bits"
1568 );
1569 }
1570
1571 #[test]
1572 fn test_not_with_multi_byte_remainder_preserves_boundary_bits() {
1573 let mut buffer = vec![0b00000000u8, 0b00000000u8, 0b11111111u8];
1574 apply_bitwise_unary_op(&mut buffer, 0, 20, |a| !a);
1576 assert_eq!(
1577 buffer,
1578 vec![0b11111111u8, 0b11111111u8, 0b11110000u8],
1579 "the boundary byte lost its out-of-range bits"
1580 );
1581 }
1582
1583 #[test]
1584 fn test_bitwise_binary_op_offset_out_of_bounds() {
1585 let input = vec![0b10101010u8, 0b01010101u8];
1586 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_binary_op(
1589 buffer.as_slice_mut(),
1590 100, [0b11110000u8, 0b00001111u8],
1592 0,
1593 0,
1594 |a, b| a & b,
1595 );
1596 assert_eq!(buffer.as_slice(), &input);
1597 }
1598
1599 #[test]
1600 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
1601 fn test_bitwise_binary_op_length_out_of_bounds() {
1602 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1605 buffer.as_slice_mut(),
1606 0, [0b11110000u8, 0b00001111u8],
1608 0,
1609 100,
1610 |a, b| a & b,
1611 );
1612 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1613 }
1614
1615 #[test]
1616 #[should_panic(expected = "offset + len out of bounds")]
1617 fn test_bitwise_binary_op_right_len_out_of_bounds() {
1618 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1621 buffer.as_slice_mut(),
1622 0, [0b11110000u8, 0b00001111u8],
1624 1000,
1625 16,
1626 |a, b| a & b,
1627 );
1628 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1629 }
1630
1631 #[test]
1632 #[should_panic(expected = "the len is 2 but the index is 12")]
1633 fn test_bitwise_unary_op_offset_out_of_bounds() {
1634 let input = vec![0b10101010u8, 0b01010101u8];
1635 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
1638 buffer.as_slice_mut(),
1639 100, 8,
1641 |a| !a,
1642 );
1643 assert_eq!(buffer.as_slice(), &input);
1644 }
1645
1646 #[test]
1647 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
1648 fn test_bitwise_unary_op_length_out_of_bounds2() {
1649 let input = vec![0b10101010u8, 0b01010101u8];
1650 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
1653 buffer.as_slice_mut(),
1654 3, 100, |a| !a,
1657 );
1658 assert_eq!(buffer.as_slice(), &input);
1659 }
1660}