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 Adc;
impl Algorithm for Adc {
const NAME: &'static str = "adc";
type Encoder = Encoder;
type Decoder = Decoder;
type EncoderConfig = ();
type DecoderConfig = ();
fn encoder_with(_: ()) -> Encoder {
Encoder::new()
}
fn decoder_with(_: ()) -> Decoder {
Decoder::new()
}
}
const MAX_LONG_OFFSET: usize = 65536;
const MAX_SHORT_OFFSET: usize = 1024;
const MAX_LONG_MATCH: usize = 67;
const MAX_SHORT_MATCH: usize = 18;
const MIN_MATCH: usize = 3;
const MAX_LITERAL_RUN: usize = 128;
const HASH_LOG: u32 = 13;
const HASH_TABLE_SIZE: usize = 1 << HASH_LOG;
const HASH_EMPTY: u32 = u32::MAX;
#[inline]
fn hash3(b0: u8, b1: u8, b2: u8) -> usize {
let v = (b0 as u32) | ((b1 as u32) << 8) | ((b2 as u32) << 16);
((v.wrapping_mul(2_654_435_761)) >> (32 - HASH_LOG)) as usize
}
#[derive(Clone, Copy, PartialEq, Eq)]
enum EncPhase {
Buffering,
Flushing,
Done,
}
pub struct Encoder {
input: Vec<u8>,
encoded: Vec<u8>,
encoded_idx: usize,
phase: EncPhase,
}
impl Encoder {
pub fn new() -> Self {
Self {
input: Vec::new(),
encoded: Vec::new(),
encoded_idx: 0,
phase: EncPhase::Buffering,
}
}
fn build(&mut self) {
self.encoded.clear();
self.encoded_idx = 0;
if self.input.is_empty() {
self.phase = EncPhase::Done;
return;
}
let mut hash_table = vec![HASH_EMPTY; HASH_TABLE_SIZE];
let input = &self.input;
let n = input.len();
let mut pending_lit_start: usize = 0;
let mut pending_lit_len: usize = 0;
let mut i: usize = 0;
let flush_literals = |encoded: &mut Vec<u8>,
input: &[u8],
pending_lit_start: usize,
pending_lit_len: usize| {
let mut off = pending_lit_start;
let mut rem = pending_lit_len;
while rem > 0 {
let take = rem.min(MAX_LITERAL_RUN);
encoded.push(0x80 | ((take - 1) as u8));
encoded.extend_from_slice(&input[off..off + take]);
off += take;
rem -= take;
}
};
while i + MIN_MATCH <= n {
let h = hash3(input[i], input[i + 1], input[i + 2]);
let prev_pos = hash_table[h] as usize;
let prev_pos_valid = hash_table[h] != HASH_EMPTY && prev_pos < i;
let mut best_len: usize = 0;
let mut best_dist: usize = 0;
if prev_pos_valid {
let dist = i - prev_pos;
if (1..=MAX_LONG_OFFSET).contains(&dist) {
if input[prev_pos] == input[i]
&& input[prev_pos + 1] == input[i + 1]
&& input[prev_pos + 2] == input[i + 2]
{
let mut len = 3usize;
let limit = (n - i).min(MAX_LONG_MATCH);
while len < limit && input[prev_pos + len] == input[i + len] {
len += 1;
}
if dist <= MAX_SHORT_OFFSET {
best_len = len;
best_dist = dist;
} else if len >= 4 {
best_len = len;
best_dist = dist;
}
}
}
}
hash_table[h] = i as u32;
if best_len >= MIN_MATCH {
if pending_lit_len > 0 {
flush_literals(&mut self.encoded, input, pending_lit_start, pending_lit_len);
pending_lit_len = 0;
}
if best_dist <= MAX_SHORT_OFFSET && best_len <= MAX_SHORT_MATCH {
let off_code = (best_dist - 1) as u16;
let len_code = (best_len - MIN_MATCH) as u8; let tag = ((len_code & 0x0F) << 2) | ((off_code >> 8) as u8 & 0x03);
self.encoded.push(tag);
self.encoded.push((off_code & 0xFF) as u8);
} else {
let len = best_len.min(MAX_LONG_MATCH);
let len_code = (len - 4) as u8; let tag = 0x40 | (len_code & 0x3F);
let off_code = (best_dist - 1) as u16;
self.encoded.push(tag);
self.encoded.push((off_code >> 8) as u8);
self.encoded.push((off_code & 0xFF) as u8);
}
let match_end = i + best_len;
let mut j = i + 1;
while j + MIN_MATCH <= match_end.min(n) && j < n - 2 {
let h2 = hash3(input[j], input[j + 1], input[j + 2]);
hash_table[h2] = j as u32;
j += 1;
}
i = match_end;
pending_lit_start = i;
} else {
pending_lit_len += 1;
i += 1;
}
}
if i < n {
pending_lit_len += n - i;
}
if pending_lit_len > 0 {
flush_literals(&mut self.encoded, input, pending_lit_start, pending_lit_len);
}
self.phase = EncPhase::Flushing;
}
fn drain_encoded(&mut self, output: &mut [u8], written: &mut usize) {
let avail = self.encoded.len() - self.encoded_idx;
let space = output.len() - *written;
let n = avail.min(space);
if n > 0 {
output[*written..*written + n]
.copy_from_slice(&self.encoded[self.encoded_idx..self.encoded_idx + n]);
self.encoded_idx += n;
*written += n;
}
if self.encoded_idx == self.encoded.len() {
self.phase = EncPhase::Done;
}
}
}
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> {
if self.phase != EncPhase::Buffering {
return Ok(RawProgress {
consumed: 0,
written: 0,
done: false,
});
}
let _ = output;
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> {
let mut written = 0usize;
loop {
match self.phase {
EncPhase::Buffering => {
self.build();
}
EncPhase::Flushing => {
self.drain_encoded(output, &mut written);
if self.phase == EncPhase::Flushing {
return Ok(RawProgress {
consumed: 0,
written,
done: false,
});
}
}
EncPhase::Done => {
return Ok(RawProgress {
consumed: 0,
written,
done: true,
});
}
}
}
}
fn raw_reset(&mut self) {
self.input.clear();
self.encoded.clear();
self.encoded_idx = 0;
self.phase = EncPhase::Buffering;
}
}
const WINDOW_SIZE: usize = 65536;
#[derive(Clone, Copy, PartialEq, Eq)]
enum DecPhase {
Tag,
Literal {
remaining: u16,
},
LongMatchOffHi {
length: u8,
},
LongMatchOffLo {
length: u8,
off_hi: u8,
},
ShortMatchOffLo {
length: u8,
off_hi: u8,
},
Copying {
distance: u32,
remaining: u16,
},
}
pub struct Decoder {
window: Vec<u8>,
window_pos: usize,
emitted: u64,
phase: DecPhase,
poisoned: bool,
}
impl Decoder {
pub fn new() -> Self {
Self {
window: vec![0u8; WINDOW_SIZE],
window_pos: 0,
emitted: 0,
phase: DecPhase::Tag,
poisoned: false,
}
}
fn emit_byte(&mut self, b: u8, output: &mut [u8], written: &mut usize) {
output[*written] = b;
*written += 1;
self.window[self.window_pos] = b;
self.window_pos = (self.window_pos + 1) % WINDOW_SIZE;
self.emitted += 1;
}
fn window_lookback(&self, distance: u32) -> u8 {
let d = distance as usize;
let idx = (self.window_pos + WINDOW_SIZE - d) % WINDOW_SIZE;
self.window[idx]
}
}
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> {
if self.poisoned {
return Err(Error::Corrupt);
}
let mut consumed = 0usize;
let mut written = 0usize;
loop {
if let DecPhase::Copying {
distance,
remaining,
} = self.phase
{
let mut rem = remaining;
while rem > 0 {
if written == output.len() {
self.phase = DecPhase::Copying {
distance,
remaining: rem,
};
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let b = self.window_lookback(distance);
self.emit_byte(b, output, &mut written);
rem -= 1;
}
self.phase = DecPhase::Tag;
continue;
}
if let DecPhase::Literal { remaining } = self.phase {
let mut rem = remaining;
while rem > 0 {
if consumed == input.len() {
self.phase = DecPhase::Literal { remaining: rem };
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
if written == output.len() {
self.phase = DecPhase::Literal { remaining: rem };
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
let b = input[consumed];
consumed += 1;
self.emit_byte(b, output, &mut written);
rem -= 1;
}
self.phase = DecPhase::Tag;
continue;
}
if consumed == input.len() {
return Ok(RawProgress {
consumed,
written,
done: false,
});
}
match self.phase {
DecPhase::Tag => {
let tag = input[consumed];
consumed += 1;
if tag & 0x80 != 0 {
let len = ((tag & 0x7F) as u16) + 1;
self.phase = DecPhase::Literal { remaining: len };
} else if tag & 0x40 != 0 {
let length = (tag & 0x3F) + 4; self.phase = DecPhase::LongMatchOffHi { length };
} else {
let length = ((tag & 0x3C) >> 2) + 3; let off_hi = tag & 0x03;
self.phase = DecPhase::ShortMatchOffLo { length, off_hi };
}
}
DecPhase::LongMatchOffHi { length } => {
let off_hi = input[consumed];
consumed += 1;
self.phase = DecPhase::LongMatchOffLo { length, off_hi };
}
DecPhase::LongMatchOffLo { length, off_hi } => {
let off_lo = input[consumed];
consumed += 1;
let offset = ((off_hi as u32) << 8) | (off_lo as u32);
let distance = offset + 1; if (distance as u64) > self.emitted {
self.poisoned = true;
return Err(Error::InvalidDistance);
}
self.phase = DecPhase::Copying {
distance,
remaining: length as u16,
};
}
DecPhase::ShortMatchOffLo { length, off_hi } => {
let off_lo = input[consumed];
consumed += 1;
let distance = (((off_hi as u32) << 8) | (off_lo as u32)) + 1;
if (distance as u64) > self.emitted {
self.poisoned = true;
return Err(Error::InvalidDistance);
}
self.phase = DecPhase::Copying {
distance,
remaining: length as u16,
};
}
DecPhase::Literal { .. } | DecPhase::Copying { .. } => {
debug_assert!(false, "should have been handled at top of loop");
}
}
}
}
fn raw_finish(&mut self, output: &mut [u8]) -> Result<RawProgress, Error> {
if self.poisoned {
return Err(Error::Corrupt);
}
let mut written = 0usize;
if let DecPhase::Copying {
distance,
remaining,
} = self.phase
{
let mut rem = remaining;
while rem > 0 {
if written == output.len() {
self.phase = DecPhase::Copying {
distance,
remaining: rem,
};
return Ok(RawProgress {
consumed: 0,
written,
done: false,
});
}
let b = self.window_lookback(distance);
self.emit_byte(b, output, &mut written);
rem -= 1;
}
self.phase = DecPhase::Tag;
}
match self.phase {
DecPhase::Tag => Ok(RawProgress {
consumed: 0,
written,
done: true,
}),
DecPhase::Literal { .. }
| DecPhase::LongMatchOffHi { .. }
| DecPhase::LongMatchOffLo { .. }
| DecPhase::ShortMatchOffLo { .. } => Err(Error::UnexpectedEnd),
DecPhase::Copying { .. } => Ok(RawProgress {
consumed: 0,
written,
done: false,
}),
}
}
fn raw_reset(&mut self) {
for b in self.window.iter_mut() {
*b = 0;
}
self.window_pos = 0;
self.emitted = 0;
self.phase = DecPhase::Tag;
self.poisoned = false;
}
}