#![cfg_attr(docsrs, doc(cfg(feature = "lzss")))]
extern crate alloc;
use alloc::vec;
use alloc::vec::Vec;
use crate::error::Error;
use crate::traits::{Algorithm, RawDecoder, RawEncoder, RawProgress};
#[derive(Debug, Clone, Copy, Default)]
pub struct Lzss;
impl Algorithm for Lzss {
const NAME: &'static str = "lzss";
type Encoder = Encoder;
type Decoder = Decoder;
type EncoderConfig = ();
type DecoderConfig = ();
fn encoder_with(_: ()) -> Encoder {
Encoder::new()
}
fn decoder_with(_: ()) -> Decoder {
Decoder::new()
}
}
const N: usize = 4096;
const F: usize = 18;
const THRESHOLD: usize = 2;
const NUL: u8 = 0x20;
#[derive(Debug)]
pub struct Encoder {
input: Vec<u8>,
output: Vec<u8>,
out_cursor: usize,
finalized: bool,
}
impl Encoder {
pub fn new() -> Self {
Self {
input: Vec::new(),
output: Vec::new(),
out_cursor: 0,
finalized: false,
}
}
fn finalize(&mut self) {
let n_data = self.input.len() as u32;
self.output.extend_from_slice(&n_data.to_le_bytes());
if self.input.is_empty() {
return;
}
let mut text_buf = vec![NUL; N + F - 1];
let mut code_buf = [0u8; 17];
let mut code_ptr: usize = 1;
let mut mask: u8 = 1;
let mut s: usize = 0;
let mut r: usize = N - F;
let mut in_pos: usize = 0;
let n = self.input.len();
let mut length: usize = 0;
while length < F && in_pos < n {
text_buf[r + length] = self.input[in_pos];
in_pos += 1;
length += 1;
}
while length > 0 {
let mut best_len: usize = 0;
let mut best_pos: usize = 0;
for i in 0..N {
let off_into_la = (i + N - r) & (N - 1);
if off_into_la < length {
continue;
}
let mut k = 0usize;
while k < length && text_buf[(i + k) & (N - 1)] == text_buf[r + k] {
k += 1;
if k >= F {
break;
}
}
if k > best_len {
best_len = k;
best_pos = i;
if k >= F {
break;
}
} else if k == best_len && k > 0 && i < best_pos {
best_pos = i;
}
}
if best_len <= THRESHOLD {
best_len = 1;
code_buf[0] |= mask;
code_buf[code_ptr] = text_buf[r];
code_ptr += 1;
} else {
code_buf[code_ptr] = (best_pos & 0xFF) as u8;
code_ptr += 1;
code_buf[code_ptr] =
(((best_pos >> 4) & 0xF0) | ((best_len - (THRESHOLD + 1)) & 0x0F)) as u8;
code_ptr += 1;
}
mask = mask.wrapping_shl(1);
if mask == 0 {
self.output.extend_from_slice(&code_buf[..code_ptr]);
code_buf[0] = 0;
code_ptr = 1;
mask = 1;
}
let last_len = best_len;
let mut i = 0usize;
while i < last_len && in_pos < n {
let c = self.input[in_pos];
in_pos += 1;
text_buf[s] = c;
if s < F - 1 {
text_buf[s + N] = c;
}
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
i += 1;
}
while i < last_len {
s = (s + 1) & (N - 1);
r = (r + 1) & (N - 1);
length -= 1;
if length == 0 {
break;
}
i += 1;
}
}
if code_ptr > 1 {
self.output.extend_from_slice(&code_buf[..code_ptr]);
}
}
}
impl Default for Encoder {
fn default() -> Self {
Self::new()
}
}
impl RawEncoder for Encoder {
fn raw_encode(&mut self, input: &[u8], _output: &mut [u8]) -> Result<RawProgress, Error> {
self.input.extend_from_slice(input);
Ok(RawProgress {
consumed: input.len(),
written: 0,
done: false,
})
}
fn raw_finish(&mut self, output: &mut [u8]) -> Result<RawProgress, Error> {
if !self.finalized {
self.finalize();
self.finalized = true;
}
let remaining = self.output.len() - self.out_cursor;
let n = remaining.min(output.len());
output[..n].copy_from_slice(&self.output[self.out_cursor..self.out_cursor + n]);
self.out_cursor += n;
let done = self.out_cursor >= self.output.len();
Ok(RawProgress {
consumed: 0,
written: n,
done,
})
}
fn raw_reset(&mut self) {
self.input.clear();
self.output.clear();
self.out_cursor = 0;
self.finalized = false;
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum DecPhase {
Header,
Flags,
Token,
NeedLiteral,
PendingLiteral,
NeedMatch1,
NeedMatch2,
EmitMatch,
Done,
}
#[derive(Debug)]
pub struct Decoder {
phase: DecPhase,
header_buf: [u8; 4],
header_pos: u8,
expected_len: u32,
emitted: u32,
flags: u8,
flags_left: u8,
match_first: u8,
match_pos: u16,
match_len: u8,
pending_literal: u8,
ring: Vec<u8>,
ring_w: usize,
}
impl Decoder {
pub fn new() -> Self {
Self {
phase: DecPhase::Header,
header_buf: [0u8; 4],
header_pos: 0,
expected_len: 0,
emitted: 0,
flags: 0,
flags_left: 0,
match_first: 0,
match_pos: 0,
match_len: 0,
pending_literal: 0,
ring: vec![NUL; N],
ring_w: N - F,
}
}
fn emit(&mut self, b: u8, output: &mut [u8], written: &mut usize) -> bool {
if *written >= output.len() {
return false;
}
output[*written] = b;
*written += 1;
self.ring[self.ring_w] = b;
self.ring_w = (self.ring_w + 1) & (N - 1);
self.emitted = self.emitted.saturating_add(1);
if self.emitted >= self.expected_len {
self.phase = DecPhase::Done;
}
true
}
}
impl Default for Decoder {
fn default() -> Self {
Self::new()
}
}
impl RawDecoder for Decoder {
fn raw_decode(&mut self, input: &[u8], output: &mut [u8]) -> Result<RawProgress, Error> {
let mut consumed = 0usize;
let mut written = 0usize;
loop {
match self.phase {
DecPhase::Header => {
while self.header_pos < 4 && consumed < input.len() {
self.header_buf[self.header_pos as usize] = input[consumed];
self.header_pos += 1;
consumed += 1;
}
if self.header_pos < 4 {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
self.expected_len = u32::from_le_bytes(self.header_buf);
if self.expected_len == 0 {
self.phase = DecPhase::Done;
} else {
self.phase = DecPhase::Flags;
}
}
DecPhase::Flags => {
if consumed >= input.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
self.flags = input[consumed];
consumed += 1;
self.flags_left = 8;
self.phase = DecPhase::Token;
}
DecPhase::Token => {
if self.flags_left == 0 {
self.phase = DecPhase::Flags;
continue;
}
let is_literal = (self.flags & 1) != 0;
self.flags >>= 1;
self.flags_left -= 1;
self.phase = if is_literal {
DecPhase::NeedLiteral
} else {
DecPhase::NeedMatch1
};
}
DecPhase::NeedLiteral => {
if consumed >= input.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let b = input[consumed];
consumed += 1;
if !self.emit(b, output, &mut written) {
self.pending_literal = b;
self.phase = DecPhase::PendingLiteral;
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
if !matches!(self.phase, DecPhase::Done) {
self.phase = DecPhase::Token;
}
}
DecPhase::PendingLiteral => {
let b = self.pending_literal;
if !self.emit(b, output, &mut written) {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
if !matches!(self.phase, DecPhase::Done) {
self.phase = DecPhase::Token;
}
}
DecPhase::NeedMatch1 => {
if consumed >= input.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
self.match_first = input[consumed];
consumed += 1;
self.phase = DecPhase::NeedMatch2;
}
DecPhase::NeedMatch2 => {
if consumed >= input.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let b2 = input[consumed];
consumed += 1;
let pos = (self.match_first as u16) | (((b2 as u16) & 0xF0) << 4);
self.match_pos = pos & (N as u16 - 1);
self.match_len = (b2 & 0x0F) + (THRESHOLD as u8) + 1;
self.phase = DecPhase::EmitMatch;
}
DecPhase::EmitMatch => {
while self.match_len > 0 {
let b = self.ring[self.match_pos as usize & (N - 1)];
if !self.emit(b, output, &mut written) {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
self.match_pos = (self.match_pos + 1) & (N as u16 - 1);
self.match_len -= 1;
if matches!(self.phase, DecPhase::Done) {
return Ok(RawProgress {
consumed,
written,
done: true,
});
}
}
self.phase = DecPhase::Token;
}
DecPhase::Done => {
return Ok(RawProgress {
consumed,
written,
done: true,
});
}
}
}
}
fn raw_finish(&mut self, _output: &mut [u8]) -> Result<RawProgress, Error> {
match self.phase {
DecPhase::Done => Ok(RawProgress {
consumed: 0,
written: 0,
done: true,
}),
DecPhase::Header if self.header_pos == 0 => {
self.phase = DecPhase::Done;
Ok(RawProgress {
consumed: 0,
written: 0,
done: true,
})
}
_ => Err(Error::UnexpectedEnd),
}
}
fn raw_reset(&mut self) {
self.phase = DecPhase::Header;
self.header_buf = [0u8; 4];
self.header_pos = 0;
self.expected_len = 0;
self.emitted = 0;
self.flags = 0;
self.flags_left = 0;
self.match_first = 0;
self.match_pos = 0;
self.match_len = 0;
self.pending_literal = 0;
for b in self.ring.iter_mut() {
*b = NUL;
}
self.ring_w = N - F;
}
}