use super::consts::*;
pub struct Window {
buf: [u8; BUF_SIZE + MAX_MATCH_LEN],
pos: usize,
write_pos: usize,
lookahead_len: usize,
full: bool,
}
impl Window {
pub const fn new() -> Self {
Self {
buf: [0; BUF_SIZE + MAX_MATCH_LEN],
pos: 0,
write_pos: 0,
lookahead_len: 0,
full: false,
}
}
}
impl Window {
pub fn reset<'a>(&mut self, src: &'a [u8]) -> core::slice::Iter<'a, u8> {
let (head, rest) = src.split_at(src.len().min(MAX_MATCH_LEN));
self.buf[..head.len()].copy_from_slice(head);
if head.len() < 3 {
self.buf[head.len()..head.len() + 3].fill(0);
}
self.pos = 0;
self.write_pos = head.len();
self.lookahead_len = head.len();
self.full = false;
rest.iter()
}
pub fn pos(&self) -> usize {
self.pos
}
pub fn lookahead(&self) -> &[u8] {
&self.buf[self.pos..self.pos + self.lookahead_len]
}
pub fn bytes_from(&self, pos: usize) -> &[u8] {
&self.buf[pos..]
}
pub fn behind(&self, pos: usize) -> usize {
if self.pos > pos {
self.pos - pos
} else {
BUF_SIZE - (pos - self.pos)
}
}
pub fn evicting(&self) -> Option<usize> {
self.full.then_some(self.write_pos)
}
pub fn push(&mut self, byte: Option<u8>) {
let byte = byte.unwrap_or_else(|| {
self.lookahead_len -= 1;
0
});
self.buf[self.write_pos] = byte;
if self.write_pos < MAX_MATCH_LEN {
self.buf[BUF_SIZE + self.write_pos] = byte;
}
self.write_pos += 1;
if self.write_pos == BUF_SIZE {
self.write_pos = 0;
self.full = true;
}
self.pos += 1;
if self.pos == BUF_SIZE {
self.pos = 0;
}
}
}