use alloc::vec;
use alloc::vec::Vec;
pub(super) const UNIT_SIZE: usize = 12;
pub(super) const STATE_SIZE: usize = 6;
pub(super) const CTX_OFF_NUM_STATS: usize = 0; pub(super) const CTX_OFF_SUMM_FREQ: usize = 2; pub(super) const CTX_OFF_STATS: usize = 4; pub(super) const CTX_OFF_SUFFIX: usize = 8;
pub(super) const STATE_OFF_SYMBOL: usize = 0; pub(super) const STATE_OFF_FREQ: usize = 1; pub(super) const STATE_OFF_SUCC_LOW: usize = 2; pub(super) const STATE_OFF_SUCC_HIGH: usize = 4;
pub(super) struct Arena {
data: Vec<u8>,
}
impl Arena {
pub fn new(size: usize) -> Self {
Self {
data: vec![0u8; size],
}
}
pub fn clear(&mut self) {
self.data.fill(0);
}
#[inline]
pub fn read_u8(&self, off: u32) -> Option<u8> {
self.data.get(off as usize).copied()
}
#[inline]
pub fn write_u8(&mut self, off: u32, v: u8) -> Option<()> {
*self.data.get_mut(off as usize)? = v;
Some(())
}
#[inline]
pub fn read_u16(&self, off: u32) -> Option<u16> {
let s = self.data.get(off as usize..off as usize + 2)?;
Some(u16::from_le_bytes([s[0], s[1]]))
}
#[inline]
pub fn write_u16(&mut self, off: u32, v: u16) -> Option<()> {
let bytes = v.to_le_bytes();
let slice = self.data.get_mut(off as usize..off as usize + 2)?;
slice.copy_from_slice(&bytes);
Some(())
}
#[inline]
pub fn write_u32(&mut self, off: u32, v: u32) -> Option<()> {
let bytes = v.to_le_bytes();
let slice = self.data.get_mut(off as usize..off as usize + 4)?;
slice.copy_from_slice(&bytes);
Some(())
}
}
#[inline]
pub(super) fn ctx_num_stats(a: &Arena, ctx: u32) -> Option<u16> {
a.read_u16(ctx + CTX_OFF_NUM_STATS as u32)
}
#[inline]
pub(super) fn ctx_set_num_stats(a: &mut Arena, ctx: u32, v: u16) -> Option<()> {
a.write_u16(ctx + CTX_OFF_NUM_STATS as u32, v)
}
#[inline]
pub(super) fn ctx_summ_freq(a: &Arena, ctx: u32) -> Option<u16> {
a.read_u16(ctx + CTX_OFF_SUMM_FREQ as u32)
}
#[inline]
pub(super) fn ctx_set_summ_freq(a: &mut Arena, ctx: u32, v: u16) -> Option<()> {
a.write_u16(ctx + CTX_OFF_SUMM_FREQ as u32, v)
}
#[inline]
pub(super) fn ctx_set_stats(a: &mut Arena, ctx: u32, v: u32) -> Option<()> {
a.write_u32(ctx + CTX_OFF_STATS as u32, v)
}
#[inline]
pub(super) fn ctx_set_suffix(a: &mut Arena, ctx: u32, v: u32) -> Option<()> {
a.write_u32(ctx + CTX_OFF_SUFFIX as u32, v)
}
#[inline]
pub(super) fn state_symbol(a: &Arena, st: u32) -> Option<u8> {
a.read_u8(st + STATE_OFF_SYMBOL as u32)
}
#[inline]
pub(super) fn state_set_symbol(a: &mut Arena, st: u32, v: u8) -> Option<()> {
a.write_u8(st + STATE_OFF_SYMBOL as u32, v)
}
#[inline]
pub(super) fn state_freq(a: &Arena, st: u32) -> Option<u8> {
a.read_u8(st + STATE_OFF_FREQ as u32)
}
#[inline]
pub(super) fn state_set_freq(a: &mut Arena, st: u32, v: u8) -> Option<()> {
a.write_u8(st + STATE_OFF_FREQ as u32, v)
}
#[inline]
pub(super) fn state_set_successor(a: &mut Arena, st: u32, v: u32) -> Option<()> {
a.write_u16(st + STATE_OFF_SUCC_LOW as u32, (v & 0xFFFF) as u16)?;
a.write_u16(st + STATE_OFF_SUCC_HIGH as u32, ((v >> 16) & 0xFFFF) as u16)
}
pub(super) fn swap_states(a: &mut Arena, st1: u32, st2: u32) -> Option<()> {
let mut s1 = [0u8; STATE_SIZE];
let mut s2 = [0u8; STATE_SIZE];
for i in 0..STATE_SIZE {
s1[i] = a.read_u8(st1 + i as u32)?;
s2[i] = a.read_u8(st2 + i as u32)?;
}
for i in 0..STATE_SIZE {
a.write_u8(st1 + i as u32, s2[i])?;
a.write_u8(st2 + i as u32, s1[i])?;
}
Some(())
}
#[inline]
pub(super) fn state_store(a: &mut Arena, st: u32, sym: u8, freq: u8, succ: u32) -> Option<()> {
state_set_symbol(a, st, sym)?;
state_set_freq(a, st, freq)?;
state_set_successor(a, st, succ)
}