#![cfg_attr(docsrs, doc(cfg(feature = "lzah")))]
extern crate alloc;
use alloc::vec::Vec;
mod adaptive;
mod bits;
mod offset;
use crate::error::Error;
use crate::traits::{Algorithm, RawDecoder, RawEncoder, RawProgress};
use adaptive::Tree;
use bits::BitReader;
use offset::OffsetCode;
const WINDOW: usize = 4096;
const WMASK: usize = WINDOW - 1;
const MIN_MATCH: usize = 3;
const LEN_BASE: u16 = 256;
#[derive(Debug, Clone, Copy, Default)]
pub struct Lzah;
#[derive(Debug, Clone, Copy, Default)]
pub struct DecoderConfig {
pub expected_len: Option<usize>,
}
impl DecoderConfig {
pub fn with_len(n: usize) -> Self {
Self {
expected_len: Some(n),
}
}
}
impl Algorithm for Lzah {
const NAME: &'static str = "lzah";
type Encoder = Encoder;
type Decoder = Decoder;
type EncoderConfig = ();
type DecoderConfig = DecoderConfig;
fn encoder_with(_: ()) -> Encoder {
Encoder
}
fn decoder_with(cfg: DecoderConfig) -> Decoder {
Decoder::new(cfg.expected_len)
}
}
#[derive(Debug, Clone, Copy, Default)]
pub struct Encoder;
impl RawEncoder for Encoder {
fn raw_encode(&mut self, _input: &[u8], _output: &mut [u8]) -> Result<RawProgress, Error> {
Err(Error::Unsupported)
}
fn raw_finish(&mut self, _output: &mut [u8]) -> Result<RawProgress, Error> {
Err(Error::Unsupported)
}
fn raw_reset(&mut self) {}
}
fn preseed_window() -> [u8; WINDOW] {
let mut w = [0u8; WINDOW];
let mut p = 18usize;
for v in 0u16..=255 {
for _ in 0..13 {
w[p] = v as u8;
p += 1;
}
}
for v in 0u16..=255 {
w[p] = v as u8;
p += 1;
}
for v in (0u16..=255).rev() {
w[p] = v as u8;
p += 1;
}
for _ in 0..128 {
w[p] = 0;
p += 1;
}
for _ in 0..110 {
w[p] = 0x20;
p += 1;
}
debug_assert_eq!(p, WINDOW);
w
}
fn decode_payload(payload: &[u8], expected_len: usize) -> Result<Vec<u8>, Error> {
let mut out = Vec::with_capacity(expected_len);
if expected_len == 0 {
return Ok(out);
}
let mut window = preseed_window();
let mut cursor = 0usize;
let mut br = BitReader::new(payload);
let mut tree = Tree::new();
let offset_code = OffsetCode::new();
while out.len() < expected_len {
let sym = tree.decode_symbol(|| br.get_bit())?;
if br.exhausted() {
return Err(Error::UnexpectedEnd);
}
tree.update(sym);
if sym < LEN_BASE {
let b = sym as u8;
window[cursor & WMASK] = b;
cursor = cursor.wrapping_add(1);
out.push(b);
} else {
let length = (sym - LEN_BASE) as usize + MIN_MATCH;
let h = offset_code.decode(&mut br)?;
let low6 = br.get_bits(6);
if br.exhausted() {
return Err(Error::UnexpectedEnd);
}
let distance = ((h << 6) + low6) as usize + 1; let mut src = cursor.wrapping_sub(distance) & WMASK;
for _ in 0..length {
if out.len() >= expected_len {
break;
}
let b = window[src & WMASK];
window[cursor & WMASK] = b;
src = src.wrapping_add(1);
cursor = cursor.wrapping_add(1);
out.push(b);
}
}
}
Ok(out)
}
#[derive(Debug)]
pub struct Decoder {
expected_len: Option<usize>,
input: Vec<u8>,
output: Vec<u8>,
out_cursor: usize,
decoded: bool,
}
impl Decoder {
fn new(expected_len: Option<usize>) -> Self {
Self {
expected_len,
input: Vec::new(),
output: Vec::new(),
out_cursor: 0,
decoded: false,
}
}
fn decode_all(&mut self) -> Result<(), Error> {
if self.decoded {
return Ok(());
}
match self.expected_len {
None => {
if self.input.is_empty() {
self.decoded = true;
return Ok(());
}
return Err(Error::Unsupported);
}
Some(0) => {
self.decoded = true;
return Ok(());
}
Some(n) => {
self.output = decode_payload(&self.input, n)?;
}
}
self.decoded = true;
Ok(())
}
fn drain(&mut self, output: &mut [u8]) -> RawProgress {
let remaining = self.output.len() - self.out_cursor;
let take = remaining.min(output.len());
output[..take].copy_from_slice(&self.output[self.out_cursor..self.out_cursor + take]);
self.out_cursor += take;
RawProgress {
consumed: 0,
written: take,
done: self.out_cursor >= self.output.len(),
}
}
}
impl RawDecoder for Decoder {
fn raw_decode(&mut self, input: &[u8], output: &mut [u8]) -> Result<RawProgress, Error> {
if !self.decoded {
self.input.extend_from_slice(input);
return Ok(RawProgress {
consumed: input.len(),
written: 0,
done: false,
});
}
let p = self.drain(output);
Ok(RawProgress {
consumed: 0,
written: p.written,
done: p.done,
})
}
fn raw_finish(&mut self, output: &mut [u8]) -> Result<RawProgress, Error> {
self.decode_all()?;
Ok(self.drain(output))
}
fn raw_reset(&mut self) {
self.input.clear();
self.output.clear();
self.out_cursor = 0;
self.decoded = false;
}
}