use crate::BitPtrMut;
pub unsafe fn fill(dst : BitPtrMut, bit_count : usize, value : bool) {
if (bit_count == 0) { return; }
let (dst_byte, dst_bit,) = dst.as_inner();
let dst_bit_l = dst_bit.get() as usize;
let dst_bit_r = (8isize - ((dst_bit_l + bit_count) as isize)).rem_euclid(8);
let dst_byte_count = (dst_bit_l + bit_count).div_ceil(8);
for dst_offset in 0..dst_byte_count {
let dst_byte = unsafe { dst_byte.byte_add(dst_offset) };
let mut mask = u8::MAX;
if (dst_offset == 0) {
mask = mask << dst_bit_l >> dst_bit_l;
}
if (dst_offset + 1 == dst_byte_count) {
mask = mask >> dst_bit_r << dst_bit_r;
}
if (value) {
unsafe { *dst_byte |= mask; }
} else {
unsafe { *dst_byte &= ! mask; }
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fill_within_byte_boundary() {
let mut x = 0b0101101110010110u16.to_be();
let mut y = 0b0101101110010110u16.to_be();
let xptr = unsafe { BitPtrMut::new_with_offset(&mut x as *mut _ as *mut _, 9) };
let yptr = unsafe { BitPtrMut::new_with_offset(&mut y as *mut _ as *mut _, 3) };
unsafe { fill(xptr, 4, false); }
unsafe { fill(yptr, 4, true); }
let x = u16::from_be(x);
let y = u16::from_be(y);
assert_eq!(x, 0b0101101110000110u16);
assert_eq!(y, 0b0101111110010110u16);
}
#[test]
fn fill_across_byte_boundary() {
let mut x = 0b0101101110010110u16.to_be();
let mut y = 0b0101101110010110u16.to_be();
let xptr = unsafe { BitPtrMut::new_with_offset(&mut x as *mut _ as *mut _, 7) };
let yptr = unsafe { BitPtrMut::new_with_offset(&mut y as *mut _ as *mut _, 3) };
unsafe { fill(xptr, 7, false); }
unsafe { fill(yptr, 7, true); }
let x = u16::from_be(x);
let y = u16::from_be(y);
assert_eq!(x, 0b0101101000000010u16);
assert_eq!(y, 0b0101111111010110u16);
}
#[test]
fn fill_aligned_start() {
let mut x = 0b0101101110010110u16.to_be();
let mut y = 0b0101101110010110u16.to_be();
let xptr = unsafe { BitPtrMut::new_with_offset(&mut x as *mut _ as *mut _, 8) };
let yptr = unsafe { BitPtrMut::new_with_offset(&mut y as *mut _ as *mut _, 0) };
unsafe { fill(xptr, 5, false); }
unsafe { fill(yptr, 5, true); }
let x = u16::from_be(x);
let y = u16::from_be(y);
assert_eq!(x, 0b0101101100000110u16);
assert_eq!(y, 0b1111101110010110u16);
}
#[test]
fn fill_aligned_end() {
let mut x = 0b0101101110010110u16.to_be();
let mut y = 0b0101101110010110u16.to_be();
let xptr = unsafe { BitPtrMut::new_with_offset(&mut x as *mut _ as *mut _, 5) };
let yptr = unsafe { BitPtrMut::new_with_offset(&mut y as *mut _ as *mut _, 13) };
unsafe { fill(xptr, 3, false); }
unsafe { fill(yptr, 3, true); }
let x = u16::from_be(x);
let y = u16::from_be(y);
assert_eq!(x, 0b0101100010010110u16);
assert_eq!(y, 0b0101101110010111u16);
}
}