use crate::{
consts,
encode::{FilterStrategy, StepEnc},
};
#[derive(Debug)]
pub(crate) struct Enc {
pub(crate) encode: Encoder,
pub(crate) chksum: u32,
}
impl Enc {
pub(crate) fn prepare(&mut self, len: usize, name: [u8; 4]) {
assert!(len <= consts::MAX_CHUNK_SIZE);
let len: u32 = len.try_into().unwrap();
self.encode.writer.extend_from_slice(&len.to_be_bytes());
self.chksum = consts::CRC32_INIT;
for c in name.iter().cloned() {
self.u8(c);
}
}
pub(crate) fn u8(&mut self, value: u8) {
self.encode.writer.push(value);
let index: usize = (self.chksum as u8 ^ value).into();
self.chksum = consts::CRC32_LOOKUP[index] ^ (self.chksum >> 8);
}
pub(crate) fn u32(&mut self, value: u32) {
let bytes = value.to_be_bytes();
for byte in bytes.iter().cloned() {
self.u8(byte)
}
}
pub(crate) fn raw(&mut self, raw: &[u8]) {
for byte in raw.iter() {
self.u8(*byte);
}
}
pub(crate) fn write_crc(&mut self) {
let crc = self.chksum ^ consts::CRC32_INIT;
self.encode.writer.extend_from_slice(&crc.to_be_bytes());
}
pub(crate) fn level(&self) -> u8 {
self.encode.level
}
}
#[derive(Debug)]
pub struct Encoder {
filter_strategy: Option<FilterStrategy>,
level: u8,
pub writer: Vec<u8>,
}
impl Encoder {
pub fn new() -> Self {
Encoder {
writer: Vec::default(),
filter_strategy: None,
level: 6,
}
}
pub fn filter_strategy(mut self, strategy: FilterStrategy) -> Self {
self.filter_strategy = Some(strategy);
self
}
pub fn compression_level(mut self, level: u8) -> Self {
assert!(level <= 10);
self.level = level;
self
}
pub(crate) fn into_step_enc(self) -> StepEnc {
StepEnc::new(self.into_enc())
}
fn into_enc(self) -> Enc {
Enc {
encode: self,
chksum: 0,
}
}
}