use super::WINDOW_SIZE;
#[derive(Debug)]
pub(super) struct SlidingBitmap([u64; (WINDOW_SIZE / 64) as usize]);
impl SlidingBitmap {
pub(super) fn new() -> Self {
let mut bitmap = SlidingBitmap([0u64; (WINDOW_SIZE / 64) as usize]);
bitmap.mark(0);
bitmap
}
pub(super) fn mark(&mut self, offset: u64) {
let word = (offset / 64) as usize;
let bit = offset % 64;
self.0[word] |= 1 << bit;
}
pub(super) fn is_marked(&self, offset: u64) -> bool {
let word = (offset / 64) as usize;
let bit = offset % 64;
self.0[word] & (1 << bit) != 0
}
pub(super) fn advance(&mut self, delta: u64) {
if delta >= WINDOW_SIZE {
*self = Self::new();
return;
}
let word_shift = (delta / 64) as usize;
let bit_shift = (delta % 64) as u32;
let words = (WINDOW_SIZE / 64) as usize;
if bit_shift == 0 {
for i in (0..words).rev() {
self.0[i] = if i >= word_shift {
self.0[i - word_shift]
} else {
0
};
}
} else {
for i in (0..words).rev() {
let lo = if i >= word_shift {
self.0[i - word_shift] << bit_shift
} else {
0
};
let hi = if i > word_shift {
self.0[i - word_shift - 1] >> (64 - bit_shift)
} else {
0
};
self.0[i] = lo | hi;
}
}
self.mark(0);
}
}