use generic_compression::lz::{lz77::LZ77entry, lz78::LZ78entry};
use num_traits::FromBytes;
use std::{error, io::Read};
fn deserialize_usize<R: Read>(
state: &mut R,
num_bytes: u8,
) -> Result<usize, Box<dyn error::Error>> {
let mut buffer = vec![0; num_bytes as usize];
state.read_exact(&mut buffer)?;
Ok(match num_bytes {
1 => buffer[0] as usize,
2 => u16::from_le_bytes(buffer.as_slice().try_into()?) as usize,
4 => u32::from_le_bytes(buffer.as_slice().try_into()?) as usize,
_ => u64::from_le_bytes(buffer.as_slice().try_into()?) as usize,
})
}
fn deserialize_byte<R: Read>(state: &mut R) -> Result<u8, Box<dyn error::Error>> {
let mut buffer = [0; 1];
state.read_exact(&mut buffer)?;
Ok(buffer[0])
}
pub fn deserialize_lz77<R: Read, const N: usize, T: FromBytes<Bytes = [u8; N]>>(
state: &mut R,
) -> Result<Vec<LZ77entry<T>>, Box<dyn error::Error>> {
let len = deserialize_usize(state, 8)?;
let mut result = Vec::with_capacity(len);
let window_size = deserialize_byte(state)?;
let lookahead_size = deserialize_byte(state)?;
for _ in 0..len {
let offset = deserialize_usize(state, window_size)?;
let length = deserialize_usize(state, lookahead_size)?;
let mut buffer = [0; N];
state.read_exact(&mut buffer)?;
let value = T::from_le_bytes(&buffer);
result.push(LZ77entry::from((offset, length, value)));
}
return Ok(result);
}
pub fn deserialize_lz78<R: Read, const N: usize, T: FromBytes<Bytes = [u8; N]>>(
state: &mut R,
) -> Result<Vec<LZ78entry<T>>, Box<dyn error::Error>> {
let len = deserialize_usize(state, 8)?;
let mut result = Vec::with_capacity(len);
let dict_width = deserialize_byte(state)?;
for _ in 0..len {
let index = deserialize_usize(state, dict_width)?;
let index = if index == 0 { None } else { Some(index - 1) };
let mut buffer = [0; N];
state.read_exact(&mut buffer)?;
let value = T::from_le_bytes(&buffer);
result.push(LZ78entry::from((index, value)));
}
return Ok(result);
}
pub fn deserialize_lzw<R: Read>(state: &mut R) -> Result<Vec<usize>, Box<dyn error::Error>> {
let len = deserialize_usize(state, 8)?;
let mut result = Vec::with_capacity(len);
let width = deserialize_byte(state)?;
for _ in 0..len {
let value = deserialize_usize(state, width)?;
result.push(value);
}
return Ok(result);
}