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 let ptr = bytes_for_u64.as_mut_ptr().cast::<u64>();
578
579 let this = Self {
580 ptr,
581 len: number_of_u64_we_can_fit,
582 _marker: std::marker::PhantomData,
583 };
584
585 (this, remainder)
586 }
587
588 fn len(&self) -> usize {
589 self.len
590 }
591
592 fn zip_modify(
595 mut self,
596 mut zip_iter: impl ExactSizeIterator<Item = u64>,
597 mut map: impl FnMut(u64, u64) -> u64,
598 ) {
599 assert_eq!(self.len, zip_iter.len());
600
601 if let Some(right) = zip_iter.next() {
606 unsafe {
609 self.apply_bin_op(right, &mut map);
610 }
611
612 }
614
615 for right in zip_iter {
616 self.ptr = unsafe { self.ptr.add(1) };
620
621 unsafe {
623 self.apply_bin_op(right, &mut map);
624 }
625
626 }
628 }
629
630 #[inline]
636 unsafe fn apply_bin_op(&mut self, right: u64, mut map: impl FnMut(u64, u64) -> u64) {
637 let current_input = unsafe {
640 self.ptr
641 .read_unaligned()
643 .to_le()
646 };
647
648 let combined = map(current_input, right);
649
650 unsafe { self.ptr.write_unaligned(combined) }
655 }
656
657 fn apply_unary_op(mut self, mut map: impl FnMut(u64) -> u64) {
659 if self.len == 0 {
660 return;
661 }
662
663 unsafe {
670 self.apply_bin_op(0, &mut |left, _| map(left));
672
673 }
675
676 for _ in 1..self.len {
677 self.ptr = unsafe { self.ptr.add(1) };
681
682 unsafe {
684 self.apply_bin_op(0, &mut |left, _| map(left));
686 }
687
688 }
690 }
691}
692
693#[inline]
706fn handle_mutable_buffer_remainder<F>(
707 op: &mut F,
708 start_remainder_mut_slice: &mut [u8],
709 right_remainder_bits: u64,
710 remainder_len: usize,
711) where
712 F: FnMut(u64, u64) -> u64,
713{
714 let left_remainder_bits = get_remainder_bits(start_remainder_mut_slice, remainder_len);
716
717 let rem = op(left_remainder_bits, right_remainder_bits);
719
720 set_remainder_bits(start_remainder_mut_slice, rem, remainder_len);
722}
723
724#[inline]
736fn set_remainder_bits(start_remainder_mut_slice: &mut [u8], rem: u64, remainder_len: usize) {
737 assert_ne!(
738 start_remainder_mut_slice.len(),
739 0,
740 "start_remainder_mut_slice must not be empty"
741 );
742 assert!(remainder_len < 64, "remainder_len must be less than 64");
743
744 assert_eq!(
747 start_remainder_mut_slice.len(),
748 self::ceil(remainder_len, 8),
749 "start_remainder_mut_slice length must be equal to ceil(remainder_len, 8)"
750 );
751
752 let rem = {
758 let current = start_remainder_mut_slice
763 .last()
764 .unwrap();
766
767 let current = (*current as u64) << ((start_remainder_mut_slice.len() - 1) * 8);
770
771 let inside_remainder_mask = (1 << remainder_len) - 1;
774 let outside_remainder_mask = !inside_remainder_mask;
777
778 let current = current & outside_remainder_mask;
780
781 let rem = rem & inside_remainder_mask;
783
784 current | rem
786 };
787
788 {
790 let remainder_bytes = start_remainder_mut_slice.len();
791
792 let rem = &rem.to_le_bytes()[0..remainder_bytes];
794
795 let src = rem.as_ptr();
799 unsafe {
803 std::ptr::copy_nonoverlapping(
804 src,
805 start_remainder_mut_slice.as_mut_ptr(),
806 remainder_bytes,
807 )
808 };
809 }
810}
811
812#[inline]
825fn get_remainder_bits(remainder: &[u8], remainder_len: usize) -> u64 {
826 assert!(remainder.len() < 64, "remainder_len must be less than 64");
827 assert_eq!(
828 remainder.len(),
829 self::ceil(remainder_len, 8),
830 "remainder and remainder len ceil must be the same"
831 );
832
833 let bits = remainder
834 .iter()
835 .enumerate()
836 .fold(0_u64, |acc, (index, &byte)| {
837 acc | ((byte as u64) << (index * 8))
838 });
839
840 bits & ((1 << remainder_len) - 1)
841}
842
843#[inline]
854fn handle_mutable_buffer_remainder_unary<F>(
855 op: &mut F,
856 start_remainder_mut: &mut [u8],
857 remainder_len: usize,
858) where
859 F: FnMut(u64) -> u64,
860{
861 let left_remainder_bits = get_remainder_bits(start_remainder_mut, remainder_len);
863
864 let rem = op(left_remainder_bits);
866
867 set_remainder_bits(start_remainder_mut, rem, remainder_len);
869}
870
871#[cfg(test)]
872mod tests {
873 use std::collections::HashSet;
874
875 use super::*;
876 use crate::bit_iterator::BitIterator;
877 use crate::{BooleanBuffer, BooleanBufferBuilder, MutableBuffer};
878 use rand::rngs::StdRng;
879 use rand::{RngExt, SeedableRng};
880
881 #[test]
882 fn test_round_upto_multiple_of_64() {
883 assert_eq!(0, round_upto_multiple_of_64(0));
884 assert_eq!(64, round_upto_multiple_of_64(1));
885 assert_eq!(64, round_upto_multiple_of_64(63));
886 assert_eq!(64, round_upto_multiple_of_64(64));
887 assert_eq!(128, round_upto_multiple_of_64(65));
888 assert_eq!(192, round_upto_multiple_of_64(129));
889 }
890
891 #[test]
892 #[should_panic(expected = "failed to round upto multiple of 64")]
893 fn test_round_upto_multiple_of_64_panic() {
894 let _ = round_upto_multiple_of_64(usize::MAX);
895 }
896
897 #[test]
898 #[should_panic(expected = "failed to round to next highest power of 2")]
899 fn test_round_upto_panic() {
900 let _ = round_upto_power_of_2(usize::MAX, 2);
901 }
902
903 #[test]
904 fn test_get_bit() {
905 assert!(get_bit(&[0b00001101], 0));
907 assert!(!get_bit(&[0b00001101], 1));
908 assert!(get_bit(&[0b00001101], 2));
909 assert!(get_bit(&[0b00001101], 3));
910
911 assert!(get_bit(&[0b01001001, 0b01010010], 0));
913 assert!(!get_bit(&[0b01001001, 0b01010010], 1));
914 assert!(!get_bit(&[0b01001001, 0b01010010], 2));
915 assert!(get_bit(&[0b01001001, 0b01010010], 3));
916 assert!(!get_bit(&[0b01001001, 0b01010010], 4));
917 assert!(!get_bit(&[0b01001001, 0b01010010], 5));
918 assert!(get_bit(&[0b01001001, 0b01010010], 6));
919 assert!(!get_bit(&[0b01001001, 0b01010010], 7));
920 assert!(!get_bit(&[0b01001001, 0b01010010], 8));
921 assert!(get_bit(&[0b01001001, 0b01010010], 9));
922 assert!(!get_bit(&[0b01001001, 0b01010010], 10));
923 assert!(!get_bit(&[0b01001001, 0b01010010], 11));
924 assert!(get_bit(&[0b01001001, 0b01010010], 12));
925 assert!(!get_bit(&[0b01001001, 0b01010010], 13));
926 assert!(get_bit(&[0b01001001, 0b01010010], 14));
927 assert!(!get_bit(&[0b01001001, 0b01010010], 15));
928 }
929
930 pub fn seedable_rng() -> StdRng {
931 StdRng::seed_from_u64(42)
932 }
933
934 #[test]
935 fn test_get_bit_raw() {
936 const NUM_BYTE: usize = 10;
937 let mut buf = [0; NUM_BYTE];
938 let mut expected = vec![];
939 let mut rng = seedable_rng();
940 for i in 0..8 * NUM_BYTE {
941 let b = rng.random_bool(0.5);
942 expected.push(b);
943 if b {
944 set_bit(&mut buf[..], i)
945 }
946 }
947
948 let raw_ptr = buf.as_ptr();
949 for (i, b) in expected.iter().enumerate() {
950 unsafe {
951 assert_eq!(*b, get_bit_raw(raw_ptr, i));
952 }
953 }
954 }
955
956 #[test]
957 fn test_set_bit() {
958 let mut b = [0b00000010];
959 set_bit(&mut b, 0);
960 assert_eq!([0b00000011], b);
961 set_bit(&mut b, 1);
962 assert_eq!([0b00000011], b);
963 set_bit(&mut b, 7);
964 assert_eq!([0b10000011], b);
965 }
966
967 #[test]
968 fn test_unset_bit() {
969 let mut b = [0b11111101];
970 unset_bit(&mut b, 0);
971 assert_eq!([0b11111100], b);
972 unset_bit(&mut b, 1);
973 assert_eq!([0b11111100], b);
974 unset_bit(&mut b, 7);
975 assert_eq!([0b01111100], b);
976 }
977
978 #[test]
979 fn test_set_bit_raw() {
980 const NUM_BYTE: usize = 10;
981 let mut buf = vec![0; NUM_BYTE];
982 let mut expected = vec![];
983 let mut rng = seedable_rng();
984 for i in 0..8 * NUM_BYTE {
985 let b = rng.random_bool(0.5);
986 expected.push(b);
987 if b {
988 unsafe {
989 set_bit_raw(buf.as_mut_ptr(), i);
990 }
991 }
992 }
993
994 let raw_ptr = buf.as_ptr();
995 for (i, b) in expected.iter().enumerate() {
996 unsafe {
997 assert_eq!(*b, get_bit_raw(raw_ptr, i));
998 }
999 }
1000 }
1001
1002 #[test]
1003 fn test_unset_bit_raw() {
1004 const NUM_BYTE: usize = 10;
1005 let mut buf = vec![255; NUM_BYTE];
1006 let mut expected = vec![];
1007 let mut rng = seedable_rng();
1008 for i in 0..8 * NUM_BYTE {
1009 let b = rng.random_bool(0.5);
1010 expected.push(b);
1011 if !b {
1012 unsafe {
1013 unset_bit_raw(buf.as_mut_ptr(), i);
1014 }
1015 }
1016 }
1017
1018 let raw_ptr = buf.as_ptr();
1019 for (i, b) in expected.iter().enumerate() {
1020 unsafe {
1021 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1022 }
1023 }
1024 }
1025
1026 #[test]
1027 fn test_get_set_bit_roundtrip() {
1028 const NUM_BYTES: usize = 10;
1029 const NUM_SETS: usize = 10;
1030
1031 let mut buffer: [u8; NUM_BYTES * 8] = [0; NUM_BYTES * 8];
1032 let mut v = HashSet::new();
1033 let mut rng = seedable_rng();
1034 for _ in 0..NUM_SETS {
1035 let offset = rng.random_range(0..8 * NUM_BYTES);
1036 v.insert(offset);
1037 set_bit(&mut buffer[..], offset);
1038 }
1039 for i in 0..NUM_BYTES * 8 {
1040 assert_eq!(v.contains(&i), get_bit(&buffer[..], i));
1041 }
1042 }
1043
1044 #[test]
1045 fn test_ceil() {
1046 assert_eq!(ceil(0, 1), 0);
1047 assert_eq!(ceil(1, 1), 1);
1048 assert_eq!(ceil(1, 2), 1);
1049 assert_eq!(ceil(1, 8), 1);
1050 assert_eq!(ceil(7, 8), 1);
1051 assert_eq!(ceil(8, 8), 1);
1052 assert_eq!(ceil(9, 8), 2);
1053 assert_eq!(ceil(9, 9), 1);
1054 assert_eq!(ceil(10000000000, 10), 1000000000);
1055 assert_eq!(ceil(10, 10000000000), 1);
1056 assert_eq!(ceil(10000000000, 1000000000), 10);
1057 }
1058
1059 #[test]
1060 fn test_read_up_to() {
1061 let all_ones = &[0b10111001, 0b10001100];
1062
1063 for (bit_offset, expected) in [
1064 (0, 0b00000001),
1065 (1, 0b00000000),
1066 (2, 0b00000000),
1067 (3, 0b00000001),
1068 (4, 0b00000001),
1069 (5, 0b00000001),
1070 (6, 0b00000000),
1071 (7, 0b00000001),
1072 ] {
1073 let result = read_up_to_byte_from_offset(all_ones, 1, bit_offset);
1074 assert_eq!(
1075 result, expected,
1076 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1077 );
1078 }
1079
1080 for (bit_offset, expected) in [
1081 (0, 0b00000001),
1082 (1, 0b00000000),
1083 (2, 0b00000010),
1084 (3, 0b00000011),
1085 (4, 0b00000011),
1086 (5, 0b00000001),
1087 (6, 0b00000010),
1088 (7, 0b00000001),
1089 ] {
1090 let result = read_up_to_byte_from_offset(all_ones, 2, bit_offset);
1091 assert_eq!(
1092 result, expected,
1093 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1094 );
1095 }
1096
1097 for (bit_offset, expected) in [
1098 (0, 0b00111001),
1099 (1, 0b00011100),
1100 (2, 0b00101110),
1101 (3, 0b00010111),
1102 (4, 0b00001011),
1103 (5, 0b00100101),
1104 (6, 0b00110010),
1105 (7, 0b00011001),
1106 ] {
1107 let result = read_up_to_byte_from_offset(all_ones, 6, bit_offset);
1108 assert_eq!(
1109 result, expected,
1110 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1111 );
1112 }
1113
1114 for (bit_offset, expected) in [
1115 (0, 0b00111001),
1116 (1, 0b01011100),
1117 (2, 0b00101110),
1118 (3, 0b00010111),
1119 (4, 0b01001011),
1120 (5, 0b01100101),
1121 (6, 0b00110010),
1122 (7, 0b00011001),
1123 ] {
1124 let result = read_up_to_byte_from_offset(all_ones, 7, bit_offset);
1125 assert_eq!(
1126 result, expected,
1127 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1128 );
1129 }
1130 }
1131
1132 fn test_mutable_buffer_bin_op_helper<F, G>(
1135 left_data: &[bool],
1136 right_data: &[bool],
1137 left_offset_in_bits: usize,
1138 right_offset_in_bits: usize,
1139 len_in_bits: usize,
1140 op: F,
1141 mut expected_op: G,
1142 ) where
1143 F: FnMut(u64, u64) -> u64,
1144 G: FnMut(bool, bool) -> bool,
1145 {
1146 let mut left_buffer = BooleanBufferBuilder::new(len_in_bits);
1147 left_buffer.append_slice(left_data);
1148 let right_buffer = BooleanBuffer::from(right_data);
1149
1150 let expected: Vec<bool> = left_data
1151 .iter()
1152 .skip(left_offset_in_bits)
1153 .zip(right_data.iter().skip(right_offset_in_bits))
1154 .take(len_in_bits)
1155 .map(|(l, r)| expected_op(*l, *r))
1156 .collect();
1157
1158 let before = left_buffer.as_slice().to_vec();
1159
1160 apply_bitwise_binary_op(
1161 left_buffer.as_slice_mut(),
1162 left_offset_in_bits,
1163 right_buffer.inner(),
1164 right_offset_in_bits,
1165 len_in_bits,
1166 op,
1167 );
1168
1169 let result: Vec<bool> =
1170 BitIterator::new(left_buffer.as_slice(), left_offset_in_bits, len_in_bits).collect();
1171
1172 assert_eq!(
1173 result, expected,
1174 "Failed with left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1175 );
1176
1177 assert_bits_outside_range_preserved(
1178 &before,
1179 left_buffer.as_slice(),
1180 left_offset_in_bits,
1181 len_in_bits,
1182 &format!(
1183 "left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1184 ),
1185 );
1186 }
1187
1188 fn assert_bits_outside_range_preserved(
1191 before: &[u8],
1192 after: &[u8],
1193 offset_in_bits: usize,
1194 len_in_bits: usize,
1195 context: &str,
1196 ) {
1197 assert_eq!(before.len(), after.len());
1198 for i in 0..before.len() * 8 {
1199 if i >= offset_in_bits && i < offset_in_bits + len_in_bits {
1200 continue;
1201 }
1202 assert_eq!(
1203 get_bit(before, i),
1204 get_bit(after, i),
1205 "bit {i} outside the requested range was modified ({context})"
1206 );
1207 }
1208 }
1209
1210 fn test_mutable_buffer_unary_op_helper<F, G>(
1213 data: &[bool],
1214 offset_in_bits: usize,
1215 len_in_bits: usize,
1216 op: F,
1217 mut expected_op: G,
1218 ) where
1219 F: FnMut(u64) -> u64,
1220 G: FnMut(bool) -> bool,
1221 {
1222 let mut buffer = BooleanBufferBuilder::new(len_in_bits);
1223 buffer.append_slice(data);
1224
1225 let expected: Vec<bool> = data
1226 .iter()
1227 .skip(offset_in_bits)
1228 .take(len_in_bits)
1229 .map(|b| expected_op(*b))
1230 .collect();
1231
1232 let before = buffer.as_slice().to_vec();
1233
1234 apply_bitwise_unary_op(buffer.as_slice_mut(), offset_in_bits, len_in_bits, op);
1235
1236 let result: Vec<bool> =
1237 BitIterator::new(buffer.as_slice(), offset_in_bits, len_in_bits).collect();
1238
1239 assert_eq!(
1240 result, expected,
1241 "Failed with offset={offset_in_bits}, len={len_in_bits}"
1242 );
1243
1244 assert_bits_outside_range_preserved(
1245 &before,
1246 buffer.as_slice(),
1247 offset_in_bits,
1248 len_in_bits,
1249 &format!("offset={offset_in_bits}, len={len_in_bits}"),
1250 );
1251 }
1252
1253 fn create_test_data(len: usize) -> (Vec<bool>, Vec<bool>) {
1255 let mut rng = rand::rng();
1256 let left: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1257 let right: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1258 (left, right)
1259 }
1260
1261 fn test_all_binary_ops(
1263 left_data: &[bool],
1264 right_data: &[bool],
1265 left_offset_in_bits: usize,
1266 right_offset_in_bits: usize,
1267 len_in_bits: usize,
1268 ) {
1269 test_mutable_buffer_bin_op_helper(
1271 left_data,
1272 right_data,
1273 left_offset_in_bits,
1274 right_offset_in_bits,
1275 len_in_bits,
1276 |a, b| a & b,
1277 |a, b| a & b,
1278 );
1279
1280 test_mutable_buffer_bin_op_helper(
1282 left_data,
1283 right_data,
1284 left_offset_in_bits,
1285 right_offset_in_bits,
1286 len_in_bits,
1287 |a, b| a | b,
1288 |a, b| a | b,
1289 );
1290
1291 test_mutable_buffer_bin_op_helper(
1293 left_data,
1294 right_data,
1295 left_offset_in_bits,
1296 right_offset_in_bits,
1297 len_in_bits,
1298 |a, b| a ^ b,
1299 |a, b| a ^ b,
1300 );
1301 }
1302
1303 #[test]
1306 fn test_binary_ops_less_than_byte() {
1307 let (left, right) = create_test_data(4);
1308 test_all_binary_ops(&left, &right, 0, 0, 4);
1309 }
1310
1311 #[test]
1312 fn test_binary_ops_less_than_byte_across_boundary() {
1313 let (left, right) = create_test_data(16);
1314 test_all_binary_ops(&left, &right, 6, 6, 4);
1315 }
1316
1317 #[test]
1318 fn test_binary_ops_exactly_byte() {
1319 let (left, right) = create_test_data(16);
1320 test_all_binary_ops(&left, &right, 0, 0, 8);
1321 }
1322
1323 #[test]
1324 fn test_binary_ops_more_than_byte_less_than_u64() {
1325 let (left, right) = create_test_data(64);
1326 test_all_binary_ops(&left, &right, 0, 0, 32);
1327 }
1328
1329 #[test]
1330 fn test_binary_ops_exactly_u64() {
1331 let (left, right) = create_test_data(180);
1332 test_all_binary_ops(&left, &right, 0, 0, 64);
1333 test_all_binary_ops(&left, &right, 64, 9, 64);
1334 test_all_binary_ops(&left, &right, 8, 100, 64);
1335 test_all_binary_ops(&left, &right, 1, 15, 64);
1336 test_all_binary_ops(&left, &right, 12, 10, 64);
1337 test_all_binary_ops(&left, &right, 180 - 64, 2, 64);
1338 }
1339
1340 #[test]
1341 fn test_binary_ops_more_than_u64_not_multiple() {
1342 let (left, right) = create_test_data(200);
1343 test_all_binary_ops(&left, &right, 0, 0, 100);
1344 }
1345
1346 #[test]
1347 fn test_binary_ops_exactly_multiple_u64() {
1348 let (left, right) = create_test_data(256);
1349 test_all_binary_ops(&left, &right, 0, 0, 128);
1350 }
1351
1352 #[test]
1353 fn test_binary_ops_more_than_multiple_u64() {
1354 let (left, right) = create_test_data(300);
1355 test_all_binary_ops(&left, &right, 0, 0, 200);
1356 }
1357
1358 #[test]
1359 fn test_binary_ops_byte_aligned_no_remainder() {
1360 let (left, right) = create_test_data(200);
1361 test_all_binary_ops(&left, &right, 0, 0, 128);
1362 }
1363
1364 #[test]
1365 fn test_binary_ops_byte_aligned_with_remainder() {
1366 let (left, right) = create_test_data(200);
1367 test_all_binary_ops(&left, &right, 0, 0, 100);
1368 }
1369
1370 #[test]
1371 fn test_binary_ops_not_byte_aligned_no_remainder() {
1372 let (left, right) = create_test_data(200);
1373 test_all_binary_ops(&left, &right, 3, 3, 128);
1374 }
1375
1376 #[test]
1377 fn test_binary_ops_not_byte_aligned_with_remainder() {
1378 let (left, right) = create_test_data(200);
1379 test_all_binary_ops(&left, &right, 5, 5, 100);
1380 }
1381
1382 #[test]
1383 fn test_binary_ops_different_offsets() {
1384 let (left, right) = create_test_data(200);
1385 test_all_binary_ops(&left, &right, 3, 7, 50);
1386 }
1387
1388 #[test]
1389 fn test_binary_ops_offsets_greater_than_8_less_than_64() {
1390 let (left, right) = create_test_data(200);
1391 test_all_binary_ops(&left, &right, 13, 27, 100);
1392 }
1393
1394 #[test]
1397 fn test_not_less_than_byte() {
1398 let data = vec![true, false, true, false];
1399 test_mutable_buffer_unary_op_helper(&data, 0, 4, |a| !a, |a| !a);
1400 }
1401
1402 #[test]
1403 fn test_not_less_than_byte_across_boundary() {
1404 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1405 test_mutable_buffer_unary_op_helper(&data, 6, 4, |a| !a, |a| !a);
1406 }
1407
1408 #[test]
1409 fn test_not_exactly_byte() {
1410 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1411 test_mutable_buffer_unary_op_helper(&data, 0, 8, |a| !a, |a| !a);
1412 }
1413
1414 #[test]
1415 fn test_not_more_than_byte_less_than_u64() {
1416 let data: Vec<bool> = (0..64).map(|i| i % 2 == 0).collect();
1417 test_mutable_buffer_unary_op_helper(&data, 0, 32, |a| !a, |a| !a);
1418 }
1419
1420 #[test]
1421 fn test_not_exactly_u64() {
1422 let data: Vec<bool> = (0..128).map(|i| i % 2 == 0).collect();
1423 test_mutable_buffer_unary_op_helper(&data, 0, 64, |a| !a, |a| !a);
1424 }
1425
1426 #[test]
1427 fn test_not_more_than_u64_not_multiple() {
1428 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1429 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1430 }
1431
1432 #[test]
1433 fn test_not_exactly_multiple_u64() {
1434 let data: Vec<bool> = (0..256).map(|i| i % 2 == 0).collect();
1435 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1436 }
1437
1438 #[test]
1439 fn test_not_more_than_multiple_u64() {
1440 let data: Vec<bool> = (0..300).map(|i| i % 2 == 0).collect();
1441 test_mutable_buffer_unary_op_helper(&data, 0, 200, |a| !a, |a| !a);
1442 }
1443
1444 #[test]
1445 fn test_not_byte_aligned_no_remainder() {
1446 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1447 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1448 }
1449
1450 #[test]
1451 fn test_not_byte_aligned_with_remainder() {
1452 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1453 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1454 }
1455
1456 #[test]
1457 fn test_not_not_byte_aligned_no_remainder() {
1458 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1459 test_mutable_buffer_unary_op_helper(&data, 3, 128, |a| !a, |a| !a);
1460 }
1461
1462 #[test]
1463 fn test_not_not_byte_aligned_with_remainder() {
1464 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1465 test_mutable_buffer_unary_op_helper(&data, 5, 100, |a| !a, |a| !a);
1466 }
1467
1468 #[test]
1471 fn test_empty_length() {
1472 let (left, right) = create_test_data(16);
1473 test_all_binary_ops(&left, &right, 0, 0, 0);
1474 }
1475
1476 #[test]
1477 fn test_single_bit() {
1478 let (left, right) = create_test_data(16);
1479 test_all_binary_ops(&left, &right, 0, 0, 1);
1480 }
1481
1482 #[test]
1483 fn test_single_bit_at_offset() {
1484 let (left, right) = create_test_data(16);
1485 test_all_binary_ops(&left, &right, 7, 7, 1);
1486 }
1487
1488 #[test]
1489 fn test_not_single_bit() {
1490 let data = vec![true, false, true, false];
1491 test_mutable_buffer_unary_op_helper(&data, 0, 1, |a| !a, |a| !a);
1492 }
1493
1494 #[test]
1495 fn test_not_empty_length() {
1496 let data = vec![true, false, true, false];
1497 test_mutable_buffer_unary_op_helper(&data, 0, 0, |a| !a, |a| !a);
1498 }
1499
1500 #[test]
1501 fn test_less_than_byte_unaligned_and_not_enough_bits() {
1502 let left_offset_in_bits = 2;
1503 let right_offset_in_bits = 4;
1504 let len_in_bits = 1;
1505
1506 let right = (0..8).map(|i| (i / 2) % 2 == 0).collect::<Vec<_>>();
1508 let left = (0..3).map(|i| i % 2 == 0).collect::<Vec<_>>();
1510 test_all_binary_ops(
1511 &left,
1512 &right,
1513 left_offset_in_bits,
1514 right_offset_in_bits,
1515 len_in_bits,
1516 );
1517 }
1518
1519 #[test]
1522 fn test_ops_ending_inside_the_first_partial_byte() {
1523 let (left, right) = create_test_data(32);
1524 for offset in 1..8 {
1525 for len in 1..=(8 - offset) {
1527 test_all_binary_ops(&left, &right, offset, offset, len);
1528 test_all_binary_ops(&left, &right, offset, (offset + 3) % 8, len);
1529 test_mutable_buffer_unary_op_helper(&left, offset, len, |a| !a, |a| !a);
1530 }
1531 }
1532 }
1533
1534 #[test]
1535 fn test_and_within_first_partial_byte_preserves_trailing_bits() {
1536 let mut left = vec![0b11111111u8, 0b11111111u8];
1537 let right = vec![0b00000000u8, 0b00000000u8];
1538 apply_bitwise_binary_op(&mut left, 1, &right, 0, 1, |a, b| a & b);
1540 assert_eq!(left, vec![0b11111101u8, 0b11111111u8]);
1541 }
1542
1543 #[test]
1544 fn test_not_within_first_partial_byte_preserves_trailing_bits() {
1545 let mut buffer = vec![0b00000000u8];
1546 apply_bitwise_unary_op(&mut buffer, 3, 2, |a| !a);
1548 assert_eq!(buffer, vec![0b00011000u8]);
1549 }
1550
1551 #[test]
1555 fn test_or_with_multi_byte_remainder_preserves_boundary_bits() {
1556 let mut left = vec![0b00000000u8, 0b00000000u8, 0b11110000u8];
1557 let right = vec![0b11111111u8, 0b11111111u8, 0b11111111u8];
1558 apply_bitwise_binary_op(&mut left, 0, &right, 0, 20, |a, b| a | b);
1560 assert_eq!(
1561 left,
1562 vec![0b11111111u8, 0b11111111u8, 0b11111111u8],
1563 "the boundary byte lost its out-of-range bits"
1564 );
1565 }
1566
1567 #[test]
1568 fn test_not_with_multi_byte_remainder_preserves_boundary_bits() {
1569 let mut buffer = vec![0b00000000u8, 0b00000000u8, 0b11111111u8];
1570 apply_bitwise_unary_op(&mut buffer, 0, 20, |a| !a);
1572 assert_eq!(
1573 buffer,
1574 vec![0b11111111u8, 0b11111111u8, 0b11110000u8],
1575 "the boundary byte lost its out-of-range bits"
1576 );
1577 }
1578
1579 #[test]
1580 fn test_bitwise_binary_op_offset_out_of_bounds() {
1581 let input = vec![0b10101010u8, 0b01010101u8];
1582 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_binary_op(
1585 buffer.as_slice_mut(),
1586 100, [0b11110000u8, 0b00001111u8],
1588 0,
1589 0,
1590 |a, b| a & b,
1591 );
1592 assert_eq!(buffer.as_slice(), &input);
1593 }
1594
1595 #[test]
1596 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
1597 fn test_bitwise_binary_op_length_out_of_bounds() {
1598 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1601 buffer.as_slice_mut(),
1602 0, [0b11110000u8, 0b00001111u8],
1604 0,
1605 100,
1606 |a, b| a & b,
1607 );
1608 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1609 }
1610
1611 #[test]
1612 #[should_panic(expected = "offset + len out of bounds")]
1613 fn test_bitwise_binary_op_right_len_out_of_bounds() {
1614 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1617 buffer.as_slice_mut(),
1618 0, [0b11110000u8, 0b00001111u8],
1620 1000,
1621 16,
1622 |a, b| a & b,
1623 );
1624 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1625 }
1626
1627 #[test]
1628 #[should_panic(expected = "the len is 2 but the index is 12")]
1629 fn test_bitwise_unary_op_offset_out_of_bounds() {
1630 let input = vec![0b10101010u8, 0b01010101u8];
1631 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
1634 buffer.as_slice_mut(),
1635 100, 8,
1637 |a| !a,
1638 );
1639 assert_eq!(buffer.as_slice(), &input);
1640 }
1641
1642 #[test]
1643 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
1644 fn test_bitwise_unary_op_length_out_of_bounds2() {
1645 let input = vec![0b10101010u8, 0b01010101u8];
1646 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
1649 buffer.as_slice_mut(),
1650 3, 100, |a| !a,
1653 );
1654 assert_eq!(buffer.as_slice(), &input);
1655 }
1656}