#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
use bytemuck::{Zeroable, allocation::zeroed_box};
#[derive(Debug, Clone, Copy, Zeroable)]
pub(super) struct HistoryNode {
prev: u8,
next: u8,
}
#[derive(Debug, Clone, Copy, Zeroable)]
pub(super) struct HistoryLinkedList {
history: [HistoryNode; 256],
history_head: u8
}
impl HistoryLinkedList {
pub(super) fn new_boxed() -> Box<Self> {
let mut history = zeroed_box::<Self>();
history.initialize();
history
}
fn initialize(&mut self) {
for (node, i) in self.history.iter_mut().zip(0..=u8::MAX) {
node.prev = i.wrapping_add(1);
node.next = i.wrapping_sub(1)
}
self.history_head = 0x20;
self.history[0x7f].prev = 0x00; self.history[0x00].next = 0x7f;
self.history[0x1f].prev = 0xa0; self.history[0xa0].next = 0x1f;
self.history[0xdf].prev = 0x80; self.history[0x80].next = 0xdf;
self.history[0x9f].prev = 0xe0; self.history[0xe0].next = 0x9f;
self.history[0xff].prev = 0x20; self.history[0x20].next = 0xff;
}
#[inline]
pub(super) fn find_in_history_list(&self, count: u8) -> u8 {
let mut code = self.history_head;
if count < 128 {
for _ in 0..usize::from(count) {
code = self.history[usize::from(code)].prev;
}
}
else {
for _ in 0..usize::from(0u8.wrapping_sub(count)) {
code = self.history[usize::from(code)].next;
}
}
code
}
#[inline]
pub(super) fn update_history_list(&mut self, byte: u8) {
let head = self.history_head;
if head == byte {
return
}
let mut node = self.history[usize::from(byte)];
self.history[usize::from(node.next)].prev = node.prev;
self.history[usize::from(node.prev)].next = node.next;
let old_head = self.history[usize::from(head)];
node.prev = head;
node.next = old_head.next;
self.history[usize::from(byte)] = node;
self.history[usize::from(old_head.next)].prev = byte;
self.history[usize::from(head)].next = byte;
self.history_head = byte;
}
}