1use crate::bit_chunk_iterator::BitChunks;
21
22#[inline]
66pub fn compress(value: u64, mask: u64) -> u64 {
67 #[cfg(all(target_arch = "x86_64", target_feature = "bmi2"))]
68 {
69 unsafe { std::arch::x86_64::_pext_u64(value, mask) }
72 }
73
74 #[cfg(not(all(target_arch = "x86_64", target_feature = "bmi2")))]
75 {
76 compress_portable(value, mask)
77 }
78}
79
80#[cfg(any(test, not(all(target_arch = "x86_64", target_feature = "bmi2"))))]
91#[inline(always)]
92fn compress_portable(value: u64, mask: u64) -> u64 {
93 let kept = mask.count_ones();
94 if kept <= 2 {
95 let lowest = mask & mask.wrapping_neg();
96 let second = mask ^ lowest;
97 u64::from(value & lowest != 0) | (u64::from(value & second != 0) << 1)
98 } else if kept <= 16 {
99 let mut mask = mask;
100 let mut result = 0_u64;
101 let mut dest_bit = 1_u64;
102 while mask != 0 {
103 let rest = mask & (mask - 1);
106 let lowest = mask ^ rest;
107 let keep = ((value & lowest) != 0) as u64;
108 result |= dest_bit & keep.wrapping_neg();
109 dest_bit <<= 1;
110 mask = rest;
111 }
112 result
113 } else if kept >= 62 {
114 if kept == 64 {
115 return value;
116 }
117 let mut value = value;
121 let mut dropped = !mask;
122 for _ in 0..2 {
123 let below = if dropped == 0 {
124 u64::MAX
125 } else {
126 (1 << dropped.ilog2()) - 1
127 };
128 value = (value & below) | ((value >> 1) & !below);
129 dropped &= below;
130 }
131 value
132 } else {
133 compress_bytes(value, mask)
134 }
135}
136
137#[cfg(any(test, not(all(target_arch = "x86_64", target_feature = "bmi2"))))]
139const fn repeat_byte(b: u8) -> u64 {
140 b as u64 * 0x0101_0101_0101_0101
141}
142
143#[cfg(any(test, not(all(target_arch = "x86_64", target_feature = "bmi2"))))]
152#[inline]
153fn compress_bytes(value: u64, mask: u64) -> u64 {
154 let mut packed = value & mask;
155 let mut dropped = !mask;
156 let mut shift = 1;
157 while shift < 8 {
158 let mut move_mask = dropped;
161 let mut step = shift;
162 while step < 8 {
163 move_mask ^= (move_mask << step) & repeat_byte(0xFF << step);
164 step <<= 1;
165 }
166 let moving = packed & move_mask;
167 packed ^= moving ^ ((moving >> shift) & repeat_byte(0xFF >> shift));
168 dropped &= !move_mask;
169 dropped ^= (dropped >> shift) & repeat_byte(0xFF >> shift);
170 shift <<= 1;
171 }
172 let pairs = mask - ((mask >> 1) & repeat_byte(0x55));
174 let nibbles = (pairs & repeat_byte(0x33)) + ((pairs >> 2) & repeat_byte(0x33));
175 let kept = (nibbles + (nibbles >> 4)) & repeat_byte(0x0F);
176 let dest = kept.wrapping_mul(repeat_byte(1)) << 8;
178 let mut result = 0;
179 for j in 0..8 {
180 result |= ((packed >> (8 * j)) & 0xFF) << ((dest >> (8 * j)) & 0xFF);
181 }
182 result
183}
184
185#[inline]
220pub fn expand(value: u64, mask: u64) -> u64 {
221 #[cfg(all(target_arch = "x86_64", target_feature = "bmi2"))]
222 {
223 unsafe { std::arch::x86_64::_pdep_u64(value, mask) }
226 }
227
228 #[cfg(not(all(target_arch = "x86_64", target_feature = "bmi2")))]
229 {
230 let mut value = value;
231 if value == 0 {
232 return 0;
233 }
234
235 let mut zeros = !mask;
236 if zeros.count_ones() <= 32 {
237 while zeros != 0 {
239 let lower = (1_u64 << zeros.trailing_zeros()) - 1;
240 value = (value & lower) | ((value & !lower) << 1);
241 zeros &= zeros - 1;
242 }
243 value
244 } else {
245 let mut output = 0;
246 let mut ones = mask;
247 while ones != 0 {
248 output |= (value & 1) << ones.trailing_zeros();
249 value >>= 1;
250 ones &= ones - 1;
251 }
252 output
253 }
254 }
255}
256
257#[inline]
263pub fn round_upto_multiple_of_64(num: usize) -> usize {
264 num.checked_next_multiple_of(64)
265 .expect("failed to round upto multiple of 64")
266}
267
268pub fn round_upto_power_of_2(num: usize, factor: usize) -> usize {
275 debug_assert!(factor > 0 && factor.is_power_of_two());
276 num.checked_add(factor - 1)
277 .expect("failed to round to next highest power of 2")
278 & !(factor - 1)
279}
280
281#[inline]
287pub fn get_bit(data: &[u8], i: usize) -> bool {
288 data[i / 8] & (1 << (i % 8)) != 0
289}
290
291#[inline]
298pub unsafe fn get_bit_raw(data: *const u8, i: usize) -> bool {
299 unsafe { (*data.add(i / 8) & (1 << (i % 8))) != 0 }
300}
301
302#[inline]
308pub fn set_bit(data: &mut [u8], i: usize) {
309 data[i / 8] |= 1 << (i % 8);
310}
311
312#[inline]
319pub unsafe fn set_bit_raw(data: *mut u8, i: usize) {
320 unsafe {
321 *data.add(i / 8) |= 1 << (i % 8);
322 }
323}
324
325#[inline]
331pub fn unset_bit(data: &mut [u8], i: usize) {
332 data[i / 8] &= !(1 << (i % 8));
333}
334
335#[inline]
342pub unsafe fn unset_bit_raw(data: *mut u8, i: usize) {
343 unsafe {
344 *data.add(i / 8) &= !(1 << (i % 8));
345 }
346}
347
348#[inline]
350pub fn ceil(value: usize, divisor: usize) -> usize {
351 value.div_ceil(divisor)
352}
353
354#[inline]
356pub(crate) fn read_u64(input: &[u8]) -> u64 {
357 let len = input.len().min(8);
358 let mut buf = [0_u8; 8];
359 buf[..len].copy_from_slice(input);
360 u64::from_le_bytes(buf)
361}
362
363#[inline]
381pub(crate) fn read_up_to_byte_from_offset(
382 slice: &[u8],
383 number_of_bits_to_read: usize,
384 bit_offset: usize,
385) -> u8 {
386 assert!(number_of_bits_to_read < 8, "can read up to 8 bits only");
387 assert!(bit_offset < 8, "bit offset must be less than 8");
388 assert_ne!(
389 number_of_bits_to_read, 0,
390 "number of bits to read must be greater than 0"
391 );
392 assert_ne!(slice.len(), 0, "slice must not be empty");
393
394 let number_of_bytes_to_read = ceil(number_of_bits_to_read + bit_offset, 8);
395
396 assert!(slice.len() >= number_of_bytes_to_read, "slice is too small");
398
399 let mut bits = slice[0] >> bit_offset;
400 for (i, &byte) in slice
401 .iter()
402 .take(number_of_bytes_to_read)
403 .enumerate()
404 .skip(1)
405 {
406 bits |= byte << (i * 8 - bit_offset);
407 }
408
409 bits & ((1 << number_of_bits_to_read) - 1)
410}
411
412pub fn apply_bitwise_binary_op<F>(
459 left: &mut [u8],
460 left_offset_in_bits: usize,
461 right: impl AsRef<[u8]>,
462 right_offset_in_bits: usize,
463 len_in_bits: usize,
464 mut op: F,
465) where
466 F: FnMut(u64, u64) -> u64,
467{
468 if len_in_bits == 0 {
469 return;
470 }
471
472 let bit_offset = left_offset_in_bits % 8;
474
475 let is_mutable_buffer_byte_aligned = bit_offset == 0;
476
477 if is_mutable_buffer_byte_aligned {
478 byte_aligned_bitwise_bin_op_helper(
479 left,
480 left_offset_in_bits,
481 right,
482 right_offset_in_bits,
483 len_in_bits,
484 op,
485 );
486 } else {
487 let bits_to_next_byte = (8 - bit_offset)
489 .min(len_in_bits);
492
493 {
494 let right_byte_offset = right_offset_in_bits / 8;
495
496 let right_first_byte = crate::util::bit_util::read_up_to_byte_from_offset(
498 &right.as_ref()[right_byte_offset..],
499 bits_to_next_byte,
500 right_offset_in_bits % 8,
502 );
503
504 align_to_byte(
505 left,
506 &mut |left| op(left, right_first_byte as u64),
508 left_offset_in_bits,
509 bits_to_next_byte,
510 );
511 }
512
513 let offset_in_bits = left_offset_in_bits + bits_to_next_byte;
514 let right_offset_in_bits = right_offset_in_bits + bits_to_next_byte;
515 let len_in_bits = len_in_bits.saturating_sub(bits_to_next_byte);
516
517 if len_in_bits == 0 {
518 return;
519 }
520
521 byte_aligned_bitwise_bin_op_helper(
523 left,
524 offset_in_bits,
525 right,
526 right_offset_in_bits,
527 len_in_bits,
528 op,
529 );
530 }
531}
532
533pub fn apply_bitwise_unary_op<F>(
573 buffer: &mut [u8],
574 offset_in_bits: usize,
575 len_in_bits: usize,
576 mut op: F,
577) where
578 F: FnMut(u64) -> u64,
579{
580 if len_in_bits == 0 {
581 return;
582 }
583
584 let left_bit_offset = offset_in_bits % 8;
586
587 let is_mutable_buffer_byte_aligned = left_bit_offset == 0;
588
589 if is_mutable_buffer_byte_aligned {
590 byte_aligned_bitwise_unary_op_helper(buffer, offset_in_bits, len_in_bits, op);
591 } else {
592 align_to_byte(buffer, &mut op, offset_in_bits, len_in_bits);
593
594 let bits_to_next_byte = 8 - left_bit_offset;
596
597 let offset_in_bits = offset_in_bits + bits_to_next_byte;
598 let len_in_bits = len_in_bits.saturating_sub(bits_to_next_byte);
599
600 if len_in_bits == 0 {
601 return;
602 }
603
604 byte_aligned_bitwise_unary_op_helper(buffer, offset_in_bits, len_in_bits, op);
606 }
607}
608
609#[inline]
623fn byte_aligned_bitwise_bin_op_helper<F>(
624 left: &mut [u8],
625 left_offset_in_bits: usize,
626 right: impl AsRef<[u8]>,
627 right_offset_in_bits: usize,
628 len_in_bits: usize,
629 mut op: F,
630) where
631 F: FnMut(u64, u64) -> u64,
632{
633 assert_eq!(
635 left_offset_in_bits % 8,
636 0,
637 "offset_in_bits must be byte aligned"
638 );
639
640 let (complete_u64_chunks, remainder_bytes) =
642 U64UnalignedSlice::split(left, left_offset_in_bits, len_in_bits);
643
644 let right_chunks = BitChunks::new(right.as_ref(), right_offset_in_bits, len_in_bits);
645 assert_eq!(
646 self::ceil(right_chunks.remainder_len(), 8),
647 remainder_bytes.len()
648 );
649
650 let right_chunks_iter = right_chunks.iter();
651 assert_eq!(right_chunks_iter.len(), complete_u64_chunks.len());
652
653 complete_u64_chunks.zip_modify(right_chunks_iter, &mut op);
655
656 if right_chunks.remainder_len() > 0 {
658 handle_mutable_buffer_remainder(
659 &mut op,
660 remainder_bytes,
661 right_chunks.remainder_bits(),
662 right_chunks.remainder_len(),
663 )
664 }
665}
666
667#[inline]
679fn byte_aligned_bitwise_unary_op_helper<F>(
680 buffer: &mut [u8],
681 offset_in_bits: usize,
682 len_in_bits: usize,
683 mut op: F,
684) where
685 F: FnMut(u64) -> u64,
686{
687 assert_eq!(offset_in_bits % 8, 0, "offset_in_bits must be byte aligned");
689
690 let remainder_len = len_in_bits % 64;
691
692 let (complete_u64_chunks, remainder_bytes) =
693 U64UnalignedSlice::split(buffer, offset_in_bits, len_in_bits);
694
695 assert_eq!(self::ceil(remainder_len, 8), remainder_bytes.len());
696
697 complete_u64_chunks.apply_unary_op(&mut op);
699
700 if remainder_len > 0 {
702 handle_mutable_buffer_remainder_unary(&mut op, remainder_bytes, remainder_len)
703 }
704}
705
706fn align_to_byte<F>(
720 buffer: &mut [u8],
721 op: &mut F,
722 offset_in_bits: usize,
723 remaining_len_in_bits: usize,
724) where
725 F: FnMut(u64) -> u64,
726{
727 let byte_offset = offset_in_bits / 8;
728 let bit_offset = offset_in_bits % 8;
729
730 debug_assert_ne!(bit_offset, 0, "offset_in_bits must not be byte aligned");
732
733 let first_byte: u8 = buffer[byte_offset];
735
736 let relevant_first_byte = first_byte >> bit_offset;
738
739 let result_first_byte = op(relevant_first_byte as u64) as u8;
741
742 let result_first_byte = result_first_byte << bit_offset;
744
745 let bits_in_this_byte = (8 - bit_offset).min(remaining_len_in_bits);
752 let write_mask = ((1u8 << bits_in_this_byte) - 1) << bit_offset;
753
754 let result_first_byte = (first_byte & !write_mask) | (result_first_byte & write_mask);
755
756 buffer[byte_offset] = result_first_byte;
758}
759
760struct U64UnalignedSlice<'a> {
772 ptr: *mut u64,
776
777 len: usize,
779
780 _marker: std::marker::PhantomData<&'a u8>,
782}
783
784impl<'a> U64UnalignedSlice<'a> {
785 fn split(
790 buffer: &'a mut [u8],
791 offset_in_bits: usize,
792 len_in_bits: usize,
793 ) -> (Self, &'a mut [u8]) {
794 let left_buffer_mut: &mut [u8] = {
796 let last_offset = self::ceil(offset_in_bits + len_in_bits, 8);
797 assert!(last_offset <= buffer.len());
798
799 let byte_offset = offset_in_bits / 8;
800
801 &mut buffer[byte_offset..last_offset]
802 };
803
804 let number_of_u64_we_can_fit = len_in_bits / (u64::BITS as usize);
805
806 let u64_len_in_bytes = number_of_u64_we_can_fit * size_of::<u64>();
808
809 assert!(u64_len_in_bytes <= left_buffer_mut.len());
810 let (bytes_for_u64, remainder) = left_buffer_mut.split_at_mut(u64_len_in_bytes);
811
812 #[expect(
813 clippy::cast_ptr_alignment,
814 reason = "`U64UnalignedSlice` only reads and writes through the unaligned methods"
815 )]
816 let ptr = bytes_for_u64.as_mut_ptr().cast::<u64>();
817
818 let this = Self {
819 ptr,
820 len: number_of_u64_we_can_fit,
821 _marker: std::marker::PhantomData,
822 };
823
824 (this, remainder)
825 }
826
827 fn len(&self) -> usize {
828 self.len
829 }
830
831 fn zip_modify(
834 mut self,
835 mut zip_iter: impl ExactSizeIterator<Item = u64>,
836 mut map: impl FnMut(u64, u64) -> u64,
837 ) {
838 assert_eq!(self.len, zip_iter.len());
839
840 if let Some(right) = zip_iter.next() {
845 unsafe {
848 self.apply_bin_op(right, &mut map);
849 }
850
851 }
853
854 for right in zip_iter {
855 self.ptr = unsafe { self.ptr.add(1) };
859
860 unsafe {
862 self.apply_bin_op(right, &mut map);
863 }
864
865 }
867 }
868
869 #[inline]
875 unsafe fn apply_bin_op(&mut self, right: u64, mut map: impl FnMut(u64, u64) -> u64) {
876 let current_input = unsafe {
879 self.ptr
880 .read_unaligned()
882 .to_le()
885 };
886
887 let combined = map(current_input, right);
888
889 unsafe { self.ptr.write_unaligned(combined) }
894 }
895
896 fn apply_unary_op(mut self, mut map: impl FnMut(u64) -> u64) {
898 if self.len == 0 {
899 return;
900 }
901
902 unsafe {
909 self.apply_bin_op(0, &mut |left, _| map(left));
911
912 }
914
915 for _ in 1..self.len {
916 self.ptr = unsafe { self.ptr.add(1) };
920
921 unsafe {
923 self.apply_bin_op(0, &mut |left, _| map(left));
925 }
926
927 }
929 }
930}
931
932#[inline]
945fn handle_mutable_buffer_remainder<F>(
946 op: &mut F,
947 start_remainder_mut_slice: &mut [u8],
948 right_remainder_bits: u64,
949 remainder_len: usize,
950) where
951 F: FnMut(u64, u64) -> u64,
952{
953 let left_remainder_bits = get_remainder_bits(start_remainder_mut_slice, remainder_len);
955
956 let rem = op(left_remainder_bits, right_remainder_bits);
958
959 set_remainder_bits(start_remainder_mut_slice, rem, remainder_len);
961}
962
963#[inline]
975fn set_remainder_bits(start_remainder_mut_slice: &mut [u8], rem: u64, remainder_len: usize) {
976 assert_ne!(
977 start_remainder_mut_slice.len(),
978 0,
979 "start_remainder_mut_slice must not be empty"
980 );
981 assert!(remainder_len < 64, "remainder_len must be less than 64");
982
983 assert_eq!(
986 start_remainder_mut_slice.len(),
987 self::ceil(remainder_len, 8),
988 "start_remainder_mut_slice length must be equal to ceil(remainder_len, 8)"
989 );
990
991 let rem = {
997 let current = start_remainder_mut_slice
1002 .last()
1003 .unwrap();
1005
1006 let current = (*current as u64) << ((start_remainder_mut_slice.len() - 1) * 8);
1009
1010 let inside_remainder_mask = (1 << remainder_len) - 1;
1013 let outside_remainder_mask = !inside_remainder_mask;
1016
1017 let current = current & outside_remainder_mask;
1019
1020 let rem = rem & inside_remainder_mask;
1022
1023 current | rem
1025 };
1026
1027 {
1029 let remainder_bytes = start_remainder_mut_slice.len();
1030
1031 let rem = &rem.to_le_bytes()[0..remainder_bytes];
1033
1034 let src = rem.as_ptr();
1038 unsafe {
1042 std::ptr::copy_nonoverlapping(
1043 src,
1044 start_remainder_mut_slice.as_mut_ptr(),
1045 remainder_bytes,
1046 )
1047 };
1048 }
1049}
1050
1051#[inline]
1064fn get_remainder_bits(remainder: &[u8], remainder_len: usize) -> u64 {
1065 assert!(remainder.len() < 64, "remainder_len must be less than 64");
1066 assert_eq!(
1067 remainder.len(),
1068 self::ceil(remainder_len, 8),
1069 "remainder and remainder len ceil must be the same"
1070 );
1071
1072 let bits = remainder
1073 .iter()
1074 .enumerate()
1075 .fold(0_u64, |acc, (index, &byte)| {
1076 acc | ((byte as u64) << (index * 8))
1077 });
1078
1079 bits & ((1 << remainder_len) - 1)
1080}
1081
1082#[inline]
1093fn handle_mutable_buffer_remainder_unary<F>(
1094 op: &mut F,
1095 start_remainder_mut: &mut [u8],
1096 remainder_len: usize,
1097) where
1098 F: FnMut(u64) -> u64,
1099{
1100 let left_remainder_bits = get_remainder_bits(start_remainder_mut, remainder_len);
1102
1103 let rem = op(left_remainder_bits);
1105
1106 set_remainder_bits(start_remainder_mut, rem, remainder_len);
1108}
1109
1110#[cfg(test)]
1111mod tests {
1112 use std::collections::HashSet;
1113
1114 use super::*;
1115 use crate::bit_iterator::BitIterator;
1116 use crate::{BooleanBuffer, BooleanBufferBuilder, MutableBuffer};
1117 use rand::rngs::StdRng;
1118 use rand::{RngExt, SeedableRng};
1119
1120 fn compress_reference(value: u64, mask: u64) -> u64 {
1123 (0..64)
1124 .filter(|&i| (mask >> i) & 1 == 1)
1125 .enumerate()
1126 .map(|(dest, i)| ((value >> i) & 1) << dest)
1127 .sum()
1128 }
1129
1130 #[test]
1131 fn test_compress() {
1132 assert_eq!(compress(0b1010, 0b1111), 0b1010);
1133 assert_eq!(compress(0b1010, 0b1010), 0b11);
1134 assert_eq!(compress(0b1010, 0b0101), 0);
1135 assert_eq!(compress(u64::MAX, 0), 0);
1136 assert_eq!(compress(0, u64::MAX), 0);
1137 assert_eq!(compress(u64::MAX, u64::MAX), u64::MAX);
1138
1139 let mut rng = StdRng::seed_from_u64(42);
1142 for _ in 0..1024 {
1143 let (value, mask): (u64, u64) = rng.random();
1144 assert_eq!(
1145 compress(value, mask),
1146 compress_reference(value, mask),
1147 "value={value:#x} mask={mask:#x}"
1148 );
1149 }
1150 }
1151
1152 #[test]
1153 fn test_compress_portable() {
1154 let check = |value: u64, mask: u64| {
1158 let want = compress_reference(value, mask);
1159 let kept = mask.count_ones();
1160 assert_eq!(
1161 compress_portable(value, mask),
1162 want,
1163 "value={value:#x} mask={mask:#x} kept={kept}"
1164 );
1165 };
1166 let mut rng = StdRng::seed_from_u64(42);
1167
1168 let value: u64 = rng.random();
1170 check(value, 0);
1171 check(value, u64::MAX);
1172 for i in 0..64 {
1173 check(value, 1 << i);
1174 check(value, !(1 << i));
1175 for j in i + 1..64 {
1176 let two = (1 << i) | (1 << j);
1177 check(value, two);
1178 check(value, !two);
1179 }
1180 }
1181
1182 for _ in 0..4096 {
1185 let value: u64 = rng.random();
1186 let mut sparse = u64::MAX;
1187 let mut dense = 0;
1188 for _ in 0..8 {
1189 let word: u64 = rng.random();
1190 sparse &= word;
1191 dense |= word;
1192 check(value, sparse);
1193 check(value, dense);
1194 }
1195 let kept = rng.random_range(0..=64);
1197 let mut mask = 0_u64;
1198 while mask.count_ones() < kept {
1199 mask |= 1 << rng.random_range(0..64);
1200 }
1201 check(value, mask);
1202 }
1203 }
1204
1205 #[test]
1206 fn test_expand() {
1207 fn reference(values: u64, mask: u64) -> u64 {
1208 let mut expected = 0;
1209 let mut input_idx = 0;
1210 for output_idx in 0..64 {
1211 if mask & (1 << output_idx) != 0 {
1212 expected |= ((values >> input_idx) & 1) << output_idx;
1213 input_idx += 1;
1214 }
1215 }
1216 expected
1217 }
1218
1219 assert_eq!(expand(0b1010, 0b1111), 0b1010);
1220 assert_eq!(expand(0b11, 0b1010), 0b1010);
1221 assert_eq!(expand(u64::MAX, 0), 0);
1222 assert_eq!(expand(0, u64::MAX), 0);
1223 assert_eq!(expand(0, 0x5555_5555_5555_5555), 0);
1224 assert_eq!(expand(u64::MAX, u64::MAX), u64::MAX);
1225
1226 let mut rng = StdRng::seed_from_u64(0x2b7e_1516_28ae_d2a6);
1227
1228 for bit in 0..64 {
1230 for mask in [u64::MAX, !(1 << bit), 1 << bit, 0] {
1231 for _ in 0..16 {
1232 let values = rng.random::<u64>();
1233 assert_eq!(expand(values, mask), reference(values, mask), "{mask:#x}");
1234 }
1235 }
1236 }
1237
1238 for _ in 0..20_000 {
1241 let density = rng.random_range(0.0..=1.0);
1242 let mask = (0..64).fold(0_u64, |mask, bit| {
1243 mask | ((rng.random_bool(density) as u64) << bit)
1244 });
1245 let values = rng.random::<u64>();
1246 assert_eq!(expand(compress(values, mask), mask), values & mask);
1247 assert_eq!(expand(values, mask), reference(values, mask), "{mask:#x}");
1248 }
1249 }
1250
1251 #[test]
1252 fn test_round_upto_multiple_of_64() {
1253 assert_eq!(0, round_upto_multiple_of_64(0));
1254 assert_eq!(64, round_upto_multiple_of_64(1));
1255 assert_eq!(64, round_upto_multiple_of_64(63));
1256 assert_eq!(64, round_upto_multiple_of_64(64));
1257 assert_eq!(128, round_upto_multiple_of_64(65));
1258 assert_eq!(192, round_upto_multiple_of_64(129));
1259 }
1260
1261 #[test]
1262 #[should_panic(expected = "failed to round upto multiple of 64")]
1263 fn test_round_upto_multiple_of_64_panic() {
1264 let _ = round_upto_multiple_of_64(usize::MAX);
1265 }
1266
1267 #[test]
1268 #[should_panic(expected = "failed to round to next highest power of 2")]
1269 fn test_round_upto_panic() {
1270 let _ = round_upto_power_of_2(usize::MAX, 2);
1271 }
1272
1273 #[test]
1274 fn test_get_bit() {
1275 assert!(get_bit(&[0b00001101], 0));
1277 assert!(!get_bit(&[0b00001101], 1));
1278 assert!(get_bit(&[0b00001101], 2));
1279 assert!(get_bit(&[0b00001101], 3));
1280
1281 assert!(get_bit(&[0b01001001, 0b01010010], 0));
1283 assert!(!get_bit(&[0b01001001, 0b01010010], 1));
1284 assert!(!get_bit(&[0b01001001, 0b01010010], 2));
1285 assert!(get_bit(&[0b01001001, 0b01010010], 3));
1286 assert!(!get_bit(&[0b01001001, 0b01010010], 4));
1287 assert!(!get_bit(&[0b01001001, 0b01010010], 5));
1288 assert!(get_bit(&[0b01001001, 0b01010010], 6));
1289 assert!(!get_bit(&[0b01001001, 0b01010010], 7));
1290 assert!(!get_bit(&[0b01001001, 0b01010010], 8));
1291 assert!(get_bit(&[0b01001001, 0b01010010], 9));
1292 assert!(!get_bit(&[0b01001001, 0b01010010], 10));
1293 assert!(!get_bit(&[0b01001001, 0b01010010], 11));
1294 assert!(get_bit(&[0b01001001, 0b01010010], 12));
1295 assert!(!get_bit(&[0b01001001, 0b01010010], 13));
1296 assert!(get_bit(&[0b01001001, 0b01010010], 14));
1297 assert!(!get_bit(&[0b01001001, 0b01010010], 15));
1298 }
1299
1300 pub fn seedable_rng() -> StdRng {
1301 StdRng::seed_from_u64(42)
1302 }
1303
1304 #[test]
1305 fn test_get_bit_raw() {
1306 const NUM_BYTE: usize = 10;
1307 let mut buf = [0; NUM_BYTE];
1308 let mut expected = vec![];
1309 let mut rng = seedable_rng();
1310 for i in 0..8 * NUM_BYTE {
1311 let b = rng.random_bool(0.5);
1312 expected.push(b);
1313 if b {
1314 set_bit(&mut buf[..], i)
1315 }
1316 }
1317
1318 let raw_ptr = buf.as_ptr();
1319 for (i, b) in expected.iter().enumerate() {
1320 unsafe {
1321 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1322 }
1323 }
1324 }
1325
1326 #[test]
1327 fn test_set_bit() {
1328 let mut b = [0b00000010];
1329 set_bit(&mut b, 0);
1330 assert_eq!([0b00000011], b);
1331 set_bit(&mut b, 1);
1332 assert_eq!([0b00000011], b);
1333 set_bit(&mut b, 7);
1334 assert_eq!([0b10000011], b);
1335 }
1336
1337 #[test]
1338 fn test_unset_bit() {
1339 let mut b = [0b11111101];
1340 unset_bit(&mut b, 0);
1341 assert_eq!([0b11111100], b);
1342 unset_bit(&mut b, 1);
1343 assert_eq!([0b11111100], b);
1344 unset_bit(&mut b, 7);
1345 assert_eq!([0b01111100], b);
1346 }
1347
1348 #[test]
1349 fn test_set_bit_raw() {
1350 const NUM_BYTE: usize = 10;
1351 let mut buf = vec![0; NUM_BYTE];
1352 let mut expected = vec![];
1353 let mut rng = seedable_rng();
1354 for i in 0..8 * NUM_BYTE {
1355 let b = rng.random_bool(0.5);
1356 expected.push(b);
1357 if b {
1358 unsafe {
1359 set_bit_raw(buf.as_mut_ptr(), i);
1360 }
1361 }
1362 }
1363
1364 let raw_ptr = buf.as_ptr();
1365 for (i, b) in expected.iter().enumerate() {
1366 unsafe {
1367 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1368 }
1369 }
1370 }
1371
1372 #[test]
1373 fn test_unset_bit_raw() {
1374 const NUM_BYTE: usize = 10;
1375 let mut buf = vec![255; NUM_BYTE];
1376 let mut expected = vec![];
1377 let mut rng = seedable_rng();
1378 for i in 0..8 * NUM_BYTE {
1379 let b = rng.random_bool(0.5);
1380 expected.push(b);
1381 if !b {
1382 unsafe {
1383 unset_bit_raw(buf.as_mut_ptr(), i);
1384 }
1385 }
1386 }
1387
1388 let raw_ptr = buf.as_ptr();
1389 for (i, b) in expected.iter().enumerate() {
1390 unsafe {
1391 assert_eq!(*b, get_bit_raw(raw_ptr, i));
1392 }
1393 }
1394 }
1395
1396 #[test]
1397 fn test_get_set_bit_roundtrip() {
1398 const NUM_BYTES: usize = 10;
1399 const NUM_SETS: usize = 10;
1400
1401 let mut buffer: [u8; NUM_BYTES * 8] = [0; NUM_BYTES * 8];
1402 let mut v = HashSet::new();
1403 let mut rng = seedable_rng();
1404 for _ in 0..NUM_SETS {
1405 let offset = rng.random_range(0..8 * NUM_BYTES);
1406 v.insert(offset);
1407 set_bit(&mut buffer[..], offset);
1408 }
1409 for i in 0..NUM_BYTES * 8 {
1410 assert_eq!(v.contains(&i), get_bit(&buffer[..], i));
1411 }
1412 }
1413
1414 #[test]
1415 fn test_ceil() {
1416 assert_eq!(ceil(0, 1), 0);
1417 assert_eq!(ceil(1, 1), 1);
1418 assert_eq!(ceil(1, 2), 1);
1419 assert_eq!(ceil(1, 8), 1);
1420 assert_eq!(ceil(7, 8), 1);
1421 assert_eq!(ceil(8, 8), 1);
1422 assert_eq!(ceil(9, 8), 2);
1423 assert_eq!(ceil(9, 9), 1);
1424 assert_eq!(ceil(10000000000, 10), 1000000000);
1425 assert_eq!(ceil(10, 10000000000), 1);
1426 assert_eq!(ceil(10000000000, 1000000000), 10);
1427 }
1428
1429 #[test]
1430 fn test_read_up_to() {
1431 let all_ones = &[0b10111001, 0b10001100];
1432
1433 for (bit_offset, expected) in [
1434 (0, 0b00000001),
1435 (1, 0b00000000),
1436 (2, 0b00000000),
1437 (3, 0b00000001),
1438 (4, 0b00000001),
1439 (5, 0b00000001),
1440 (6, 0b00000000),
1441 (7, 0b00000001),
1442 ] {
1443 let result = read_up_to_byte_from_offset(all_ones, 1, bit_offset);
1444 assert_eq!(
1445 result, expected,
1446 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1447 );
1448 }
1449
1450 for (bit_offset, expected) in [
1451 (0, 0b00000001),
1452 (1, 0b00000000),
1453 (2, 0b00000010),
1454 (3, 0b00000011),
1455 (4, 0b00000011),
1456 (5, 0b00000001),
1457 (6, 0b00000010),
1458 (7, 0b00000001),
1459 ] {
1460 let result = read_up_to_byte_from_offset(all_ones, 2, bit_offset);
1461 assert_eq!(
1462 result, expected,
1463 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1464 );
1465 }
1466
1467 for (bit_offset, expected) in [
1468 (0, 0b00111001),
1469 (1, 0b00011100),
1470 (2, 0b00101110),
1471 (3, 0b00010111),
1472 (4, 0b00001011),
1473 (5, 0b00100101),
1474 (6, 0b00110010),
1475 (7, 0b00011001),
1476 ] {
1477 let result = read_up_to_byte_from_offset(all_ones, 6, bit_offset);
1478 assert_eq!(
1479 result, expected,
1480 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1481 );
1482 }
1483
1484 for (bit_offset, expected) in [
1485 (0, 0b00111001),
1486 (1, 0b01011100),
1487 (2, 0b00101110),
1488 (3, 0b00010111),
1489 (4, 0b01001011),
1490 (5, 0b01100101),
1491 (6, 0b00110010),
1492 (7, 0b00011001),
1493 ] {
1494 let result = read_up_to_byte_from_offset(all_ones, 7, bit_offset);
1495 assert_eq!(
1496 result, expected,
1497 "failed at bit_offset {bit_offset}. result, expected:\n{result:08b}\n{expected:08b}"
1498 );
1499 }
1500 }
1501
1502 fn test_mutable_buffer_bin_op_helper<F, G>(
1505 left_data: &[bool],
1506 right_data: &[bool],
1507 left_offset_in_bits: usize,
1508 right_offset_in_bits: usize,
1509 len_in_bits: usize,
1510 op: F,
1511 mut expected_op: G,
1512 ) where
1513 F: FnMut(u64, u64) -> u64,
1514 G: FnMut(bool, bool) -> bool,
1515 {
1516 let mut left_buffer = BooleanBufferBuilder::new(len_in_bits);
1517 left_buffer.append_slice(left_data);
1518 let right_buffer = BooleanBuffer::from(right_data);
1519
1520 let expected: Vec<bool> = left_data
1521 .iter()
1522 .skip(left_offset_in_bits)
1523 .zip(right_data.iter().skip(right_offset_in_bits))
1524 .take(len_in_bits)
1525 .map(|(l, r)| expected_op(*l, *r))
1526 .collect();
1527
1528 let before = left_buffer.as_slice().to_vec();
1529
1530 apply_bitwise_binary_op(
1531 left_buffer.as_slice_mut(),
1532 left_offset_in_bits,
1533 right_buffer.inner(),
1534 right_offset_in_bits,
1535 len_in_bits,
1536 op,
1537 );
1538
1539 let result: Vec<bool> =
1540 BitIterator::new(left_buffer.as_slice(), left_offset_in_bits, len_in_bits).collect();
1541
1542 assert_eq!(
1543 result, expected,
1544 "Failed with left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1545 );
1546
1547 assert_bits_outside_range_preserved(
1548 &before,
1549 left_buffer.as_slice(),
1550 left_offset_in_bits,
1551 len_in_bits,
1552 &format!(
1553 "left_offset={left_offset_in_bits}, right_offset={right_offset_in_bits}, len={len_in_bits}"
1554 ),
1555 );
1556 }
1557
1558 fn assert_bits_outside_range_preserved(
1561 before: &[u8],
1562 after: &[u8],
1563 offset_in_bits: usize,
1564 len_in_bits: usize,
1565 context: &str,
1566 ) {
1567 assert_eq!(before.len(), after.len());
1568 for i in 0..before.len() * 8 {
1569 if i >= offset_in_bits && i < offset_in_bits + len_in_bits {
1570 continue;
1571 }
1572 assert_eq!(
1573 get_bit(before, i),
1574 get_bit(after, i),
1575 "bit {i} outside the requested range was modified ({context})"
1576 );
1577 }
1578 }
1579
1580 fn test_mutable_buffer_unary_op_helper<F, G>(
1583 data: &[bool],
1584 offset_in_bits: usize,
1585 len_in_bits: usize,
1586 op: F,
1587 mut expected_op: G,
1588 ) where
1589 F: FnMut(u64) -> u64,
1590 G: FnMut(bool) -> bool,
1591 {
1592 let mut buffer = BooleanBufferBuilder::new(len_in_bits);
1593 buffer.append_slice(data);
1594
1595 let expected: Vec<bool> = data
1596 .iter()
1597 .skip(offset_in_bits)
1598 .take(len_in_bits)
1599 .map(|b| expected_op(*b))
1600 .collect();
1601
1602 let before = buffer.as_slice().to_vec();
1603
1604 apply_bitwise_unary_op(buffer.as_slice_mut(), offset_in_bits, len_in_bits, op);
1605
1606 let result: Vec<bool> =
1607 BitIterator::new(buffer.as_slice(), offset_in_bits, len_in_bits).collect();
1608
1609 assert_eq!(
1610 result, expected,
1611 "Failed with offset={offset_in_bits}, len={len_in_bits}"
1612 );
1613
1614 assert_bits_outside_range_preserved(
1615 &before,
1616 buffer.as_slice(),
1617 offset_in_bits,
1618 len_in_bits,
1619 &format!("offset={offset_in_bits}, len={len_in_bits}"),
1620 );
1621 }
1622
1623 fn create_test_data(len: usize) -> (Vec<bool>, Vec<bool>) {
1625 let mut rng = rand::rng();
1626 let left: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1627 let right: Vec<bool> = (0..len).map(|_| rng.random_bool(0.5)).collect();
1628 (left, right)
1629 }
1630
1631 fn test_all_binary_ops(
1633 left_data: &[bool],
1634 right_data: &[bool],
1635 left_offset_in_bits: usize,
1636 right_offset_in_bits: usize,
1637 len_in_bits: usize,
1638 ) {
1639 test_mutable_buffer_bin_op_helper(
1641 left_data,
1642 right_data,
1643 left_offset_in_bits,
1644 right_offset_in_bits,
1645 len_in_bits,
1646 |a, b| a & b,
1647 |a, b| a & b,
1648 );
1649
1650 test_mutable_buffer_bin_op_helper(
1652 left_data,
1653 right_data,
1654 left_offset_in_bits,
1655 right_offset_in_bits,
1656 len_in_bits,
1657 |a, b| a | b,
1658 |a, b| a | b,
1659 );
1660
1661 test_mutable_buffer_bin_op_helper(
1663 left_data,
1664 right_data,
1665 left_offset_in_bits,
1666 right_offset_in_bits,
1667 len_in_bits,
1668 |a, b| a ^ b,
1669 |a, b| a ^ b,
1670 );
1671 }
1672
1673 #[test]
1676 fn test_binary_ops_less_than_byte() {
1677 let (left, right) = create_test_data(4);
1678 test_all_binary_ops(&left, &right, 0, 0, 4);
1679 }
1680
1681 #[test]
1682 fn test_binary_ops_less_than_byte_across_boundary() {
1683 let (left, right) = create_test_data(16);
1684 test_all_binary_ops(&left, &right, 6, 6, 4);
1685 }
1686
1687 #[test]
1688 fn test_binary_ops_exactly_byte() {
1689 let (left, right) = create_test_data(16);
1690 test_all_binary_ops(&left, &right, 0, 0, 8);
1691 }
1692
1693 #[test]
1694 fn test_binary_ops_more_than_byte_less_than_u64() {
1695 let (left, right) = create_test_data(64);
1696 test_all_binary_ops(&left, &right, 0, 0, 32);
1697 }
1698
1699 #[test]
1700 fn test_binary_ops_exactly_u64() {
1701 let (left, right) = create_test_data(180);
1702 test_all_binary_ops(&left, &right, 0, 0, 64);
1703 test_all_binary_ops(&left, &right, 64, 9, 64);
1704 test_all_binary_ops(&left, &right, 8, 100, 64);
1705 test_all_binary_ops(&left, &right, 1, 15, 64);
1706 test_all_binary_ops(&left, &right, 12, 10, 64);
1707 test_all_binary_ops(&left, &right, 180 - 64, 2, 64);
1708 }
1709
1710 #[test]
1711 fn test_binary_ops_more_than_u64_not_multiple() {
1712 let (left, right) = create_test_data(200);
1713 test_all_binary_ops(&left, &right, 0, 0, 100);
1714 }
1715
1716 #[test]
1717 fn test_binary_ops_exactly_multiple_u64() {
1718 let (left, right) = create_test_data(256);
1719 test_all_binary_ops(&left, &right, 0, 0, 128);
1720 }
1721
1722 #[test]
1723 fn test_binary_ops_more_than_multiple_u64() {
1724 let (left, right) = create_test_data(300);
1725 test_all_binary_ops(&left, &right, 0, 0, 200);
1726 }
1727
1728 #[test]
1729 fn test_binary_ops_byte_aligned_no_remainder() {
1730 let (left, right) = create_test_data(200);
1731 test_all_binary_ops(&left, &right, 0, 0, 128);
1732 }
1733
1734 #[test]
1735 fn test_binary_ops_byte_aligned_with_remainder() {
1736 let (left, right) = create_test_data(200);
1737 test_all_binary_ops(&left, &right, 0, 0, 100);
1738 }
1739
1740 #[test]
1741 fn test_binary_ops_not_byte_aligned_no_remainder() {
1742 let (left, right) = create_test_data(200);
1743 test_all_binary_ops(&left, &right, 3, 3, 128);
1744 }
1745
1746 #[test]
1747 fn test_binary_ops_not_byte_aligned_with_remainder() {
1748 let (left, right) = create_test_data(200);
1749 test_all_binary_ops(&left, &right, 5, 5, 100);
1750 }
1751
1752 #[test]
1753 fn test_binary_ops_different_offsets() {
1754 let (left, right) = create_test_data(200);
1755 test_all_binary_ops(&left, &right, 3, 7, 50);
1756 }
1757
1758 #[test]
1759 fn test_binary_ops_offsets_greater_than_8_less_than_64() {
1760 let (left, right) = create_test_data(200);
1761 test_all_binary_ops(&left, &right, 13, 27, 100);
1762 }
1763
1764 #[test]
1767 fn test_not_less_than_byte() {
1768 let data = vec![true, false, true, false];
1769 test_mutable_buffer_unary_op_helper(&data, 0, 4, |a| !a, |a| !a);
1770 }
1771
1772 #[test]
1773 fn test_not_less_than_byte_across_boundary() {
1774 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1775 test_mutable_buffer_unary_op_helper(&data, 6, 4, |a| !a, |a| !a);
1776 }
1777
1778 #[test]
1779 fn test_not_exactly_byte() {
1780 let data: Vec<bool> = (0..16).map(|i| i % 2 == 0).collect();
1781 test_mutable_buffer_unary_op_helper(&data, 0, 8, |a| !a, |a| !a);
1782 }
1783
1784 #[test]
1785 fn test_not_more_than_byte_less_than_u64() {
1786 let data: Vec<bool> = (0..64).map(|i| i % 2 == 0).collect();
1787 test_mutable_buffer_unary_op_helper(&data, 0, 32, |a| !a, |a| !a);
1788 }
1789
1790 #[test]
1791 fn test_not_exactly_u64() {
1792 let data: Vec<bool> = (0..128).map(|i| i % 2 == 0).collect();
1793 test_mutable_buffer_unary_op_helper(&data, 0, 64, |a| !a, |a| !a);
1794 }
1795
1796 #[test]
1797 fn test_not_more_than_u64_not_multiple() {
1798 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1799 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1800 }
1801
1802 #[test]
1803 fn test_not_exactly_multiple_u64() {
1804 let data: Vec<bool> = (0..256).map(|i| i % 2 == 0).collect();
1805 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1806 }
1807
1808 #[test]
1809 fn test_not_more_than_multiple_u64() {
1810 let data: Vec<bool> = (0..300).map(|i| i % 2 == 0).collect();
1811 test_mutable_buffer_unary_op_helper(&data, 0, 200, |a| !a, |a| !a);
1812 }
1813
1814 #[test]
1815 fn test_not_byte_aligned_no_remainder() {
1816 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1817 test_mutable_buffer_unary_op_helper(&data, 0, 128, |a| !a, |a| !a);
1818 }
1819
1820 #[test]
1821 fn test_not_byte_aligned_with_remainder() {
1822 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1823 test_mutable_buffer_unary_op_helper(&data, 0, 100, |a| !a, |a| !a);
1824 }
1825
1826 #[test]
1827 fn test_not_not_byte_aligned_no_remainder() {
1828 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1829 test_mutable_buffer_unary_op_helper(&data, 3, 128, |a| !a, |a| !a);
1830 }
1831
1832 #[test]
1833 fn test_not_not_byte_aligned_with_remainder() {
1834 let data: Vec<bool> = (0..200).map(|i| i % 2 == 0).collect();
1835 test_mutable_buffer_unary_op_helper(&data, 5, 100, |a| !a, |a| !a);
1836 }
1837
1838 #[test]
1841 fn test_empty_length() {
1842 let (left, right) = create_test_data(16);
1843 test_all_binary_ops(&left, &right, 0, 0, 0);
1844 }
1845
1846 #[test]
1847 fn test_single_bit() {
1848 let (left, right) = create_test_data(16);
1849 test_all_binary_ops(&left, &right, 0, 0, 1);
1850 }
1851
1852 #[test]
1853 fn test_single_bit_at_offset() {
1854 let (left, right) = create_test_data(16);
1855 test_all_binary_ops(&left, &right, 7, 7, 1);
1856 }
1857
1858 #[test]
1859 fn test_not_single_bit() {
1860 let data = vec![true, false, true, false];
1861 test_mutable_buffer_unary_op_helper(&data, 0, 1, |a| !a, |a| !a);
1862 }
1863
1864 #[test]
1865 fn test_not_empty_length() {
1866 let data = vec![true, false, true, false];
1867 test_mutable_buffer_unary_op_helper(&data, 0, 0, |a| !a, |a| !a);
1868 }
1869
1870 #[test]
1871 fn test_less_than_byte_unaligned_and_not_enough_bits() {
1872 let left_offset_in_bits = 2;
1873 let right_offset_in_bits = 4;
1874 let len_in_bits = 1;
1875
1876 let right = (0..8).map(|i| (i / 2) % 2 == 0).collect::<Vec<_>>();
1878 let left = (0..3).map(|i| i % 2 == 0).collect::<Vec<_>>();
1880 test_all_binary_ops(
1881 &left,
1882 &right,
1883 left_offset_in_bits,
1884 right_offset_in_bits,
1885 len_in_bits,
1886 );
1887 }
1888
1889 #[test]
1892 fn test_ops_ending_inside_the_first_partial_byte() {
1893 let (left, right) = create_test_data(32);
1894 for offset in 1..8 {
1895 for len in 1..=(8 - offset) {
1897 test_all_binary_ops(&left, &right, offset, offset, len);
1898 test_all_binary_ops(&left, &right, offset, (offset + 3) % 8, len);
1899 test_mutable_buffer_unary_op_helper(&left, offset, len, |a| !a, |a| !a);
1900 }
1901 }
1902 }
1903
1904 #[test]
1905 fn test_and_within_first_partial_byte_preserves_trailing_bits() {
1906 let mut left = vec![0b11111111u8, 0b11111111u8];
1907 let right = vec![0b00000000u8, 0b00000000u8];
1908 apply_bitwise_binary_op(&mut left, 1, &right, 0, 1, |a, b| a & b);
1910 assert_eq!(left, vec![0b11111101u8, 0b11111111u8]);
1911 }
1912
1913 #[test]
1914 fn test_not_within_first_partial_byte_preserves_trailing_bits() {
1915 let mut buffer = vec![0b00000000u8];
1916 apply_bitwise_unary_op(&mut buffer, 3, 2, |a| !a);
1918 assert_eq!(buffer, vec![0b00011000u8]);
1919 }
1920
1921 #[test]
1925 fn test_or_with_multi_byte_remainder_preserves_boundary_bits() {
1926 let mut left = vec![0b00000000u8, 0b00000000u8, 0b11110000u8];
1927 let right = vec![0b11111111u8, 0b11111111u8, 0b11111111u8];
1928 apply_bitwise_binary_op(&mut left, 0, &right, 0, 20, |a, b| a | b);
1930 assert_eq!(
1931 left,
1932 vec![0b11111111u8, 0b11111111u8, 0b11111111u8],
1933 "the boundary byte lost its out-of-range bits"
1934 );
1935 }
1936
1937 #[test]
1938 fn test_not_with_multi_byte_remainder_preserves_boundary_bits() {
1939 let mut buffer = vec![0b00000000u8, 0b00000000u8, 0b11111111u8];
1940 apply_bitwise_unary_op(&mut buffer, 0, 20, |a| !a);
1942 assert_eq!(
1943 buffer,
1944 vec![0b11111111u8, 0b11111111u8, 0b11110000u8],
1945 "the boundary byte lost its out-of-range bits"
1946 );
1947 }
1948
1949 #[test]
1950 fn test_bitwise_binary_op_offset_out_of_bounds() {
1951 let input = vec![0b10101010u8, 0b01010101u8];
1952 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_binary_op(
1955 buffer.as_slice_mut(),
1956 100, [0b11110000u8, 0b00001111u8],
1958 0,
1959 0,
1960 |a, b| a & b,
1961 );
1962 assert_eq!(buffer.as_slice(), &input);
1963 }
1964
1965 #[test]
1966 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
1967 fn test_bitwise_binary_op_length_out_of_bounds() {
1968 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1971 buffer.as_slice_mut(),
1972 0, [0b11110000u8, 0b00001111u8],
1974 0,
1975 100,
1976 |a, b| a & b,
1977 );
1978 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1979 }
1980
1981 #[test]
1982 #[should_panic(expected = "offset + len out of bounds")]
1983 fn test_bitwise_binary_op_right_len_out_of_bounds() {
1984 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&[0b10101010u8, 0b01010101u8]); apply_bitwise_binary_op(
1987 buffer.as_slice_mut(),
1988 0, [0b11110000u8, 0b00001111u8],
1990 1000,
1991 16,
1992 |a, b| a & b,
1993 );
1994 assert_eq!(buffer.as_slice(), &[0b10101010u8, 0b01010101u8]);
1995 }
1996
1997 #[test]
1998 #[should_panic(expected = "the len is 2 but the index is 12")]
1999 fn test_bitwise_unary_op_offset_out_of_bounds() {
2000 let input = vec![0b10101010u8, 0b01010101u8];
2001 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
2004 buffer.as_slice_mut(),
2005 100, 8,
2007 |a| !a,
2008 );
2009 assert_eq!(buffer.as_slice(), &input);
2010 }
2011
2012 #[test]
2013 #[should_panic(expected = "assertion failed: last_offset <= buffer.len()")]
2014 fn test_bitwise_unary_op_length_out_of_bounds2() {
2015 let input = vec![0b10101010u8, 0b01010101u8];
2016 let mut buffer = MutableBuffer::new(2); buffer.extend_from_slice(&input); apply_bitwise_unary_op(
2019 buffer.as_slice_mut(),
2020 3, 100, |a| !a,
2023 );
2024 assert_eq!(buffer.as_slice(), &input);
2025 }
2026}