Applies a bitwise operation relative to another bit-packed byte slice (right) in place Note: applies the operation 64-bits (u64) at a time. # Arguments `left` - The mutable buffer to be modified in-place `offset_in_bits` - Starting bit offset in Self buffer `right` - slice of bit-packed bytes in LSB order `right_offset_in_bits` - Starting bit offset in the right buffer `len_in_bits` - Number of
(
left: &mut [u8],
left_offset_in_bits: usize,
right: impl AsRef<[u8]>,
right_offset_in_bits: usize,
len_in_bits: usize,
mut op: F,
)
| 197 | /// |
| 198 | /// If the offset or lengths exceed the buffer or slice size. |
| 199 | pub fn apply_bitwise_binary_op<F>( |
| 200 | left: &mut [u8], |
| 201 | left_offset_in_bits: usize, |
| 202 | right: impl AsRef<[u8]>, |
| 203 | right_offset_in_bits: usize, |
| 204 | len_in_bits: usize, |
| 205 | mut op: F, |
| 206 | ) where |
| 207 | F: FnMut(u64, u64) -> u64, |
| 208 | { |
| 209 | if len_in_bits == 0 { |
| 210 | return; |
| 211 | } |
| 212 | |
| 213 | // offset inside a byte |
| 214 | let bit_offset = left_offset_in_bits % 8; |
| 215 | |
| 216 | let is_mutable_buffer_byte_aligned = bit_offset == 0; |
| 217 | |
| 218 | if is_mutable_buffer_byte_aligned { |
| 219 | byte_aligned_bitwise_bin_op_helper( |
| 220 | left, |
| 221 | left_offset_in_bits, |
| 222 | right, |
| 223 | right_offset_in_bits, |
| 224 | len_in_bits, |
| 225 | op, |
| 226 | ); |
| 227 | } else { |
| 228 | // If we are not byte aligned, run `op` on the first few bits to reach byte alignment |
| 229 | let bits_to_next_byte = (8 - bit_offset) |
| 230 | // Minimum with the amount of bits we need to process |
| 231 | // to avoid reading out of bounds |
| 232 | .min(len_in_bits); |
| 233 | |
| 234 | { |
| 235 | let right_byte_offset = right_offset_in_bits / 8; |
| 236 | |
| 237 | // Read the same amount of bits from the right buffer |
| 238 | let right_first_byte: u8 = crate::util::bit_util::read_up_to_byte_from_offset( |
| 239 | &right.as_ref()[right_byte_offset..], |
| 240 | bits_to_next_byte, |
| 241 | // Right bit offset |
| 242 | right_offset_in_bits % 8, |
| 243 | ); |
| 244 | |
| 245 | align_to_byte( |
| 246 | left, |
| 247 | // Hope it gets inlined |
| 248 | &mut |left| op(left, right_first_byte as u64), |
| 249 | left_offset_in_bits, |
| 250 | ); |
| 251 | } |
| 252 | |
| 253 | let offset_in_bits = left_offset_in_bits + bits_to_next_byte; |
| 254 | let right_offset_in_bits = right_offset_in_bits + bits_to_next_byte; |
| 255 | let len_in_bits = len_in_bits.saturating_sub(bits_to_next_byte); |
| 256 |