use alloc::vec;
use alloc::vec::Vec;
use crate::constants::DEFLATE_BLOCKTYPE_UNCOMPRESSED;
mod fast_match_finder;
const _SEQ_LENGTH_SHIFT: u32 = 23;
const _SEQ_LITRUNLEN_MASK: u32 = (1_u32 << _SEQ_LENGTH_SHIFT) - 1;
pub(crate) struct _Sequence
{
litrunlen_and_length: u32
}
#[derive(Debug, Copy, Clone)]
pub enum DeflateEncodingStrategy
{
NoCompression
}
impl DeflateEncodingStrategy
{
#[allow(dead_code)]
fn to_level(self) -> u8
{
match self
{
Self::NoCompression => 0
}
}
}
pub struct DeflateEncodingOptions
{
strategy: DeflateEncodingStrategy
}
impl Default for DeflateEncodingOptions
{
fn default() -> Self
{
DeflateEncodingOptions {
strategy: DeflateEncodingStrategy::NoCompression
}
}
}
pub struct DeflateEncoder<'a>
{
data: &'a [u8],
options: DeflateEncodingOptions,
output_position: usize,
input_position: usize,
output: Vec<u8>
}
impl<'a> DeflateEncoder<'a>
{
pub fn new(data: &'a [u8]) -> DeflateEncoder<'a>
{
DeflateEncoder::new_with_options(data, DeflateEncodingOptions::default())
}
pub fn new_with_options(data: &'a [u8], options: DeflateEncodingOptions) -> DeflateEncoder<'a>
{
let length = data.len() + 1024;
let out_array = vec![0; length];
DeflateEncoder {
data,
options,
output_position: 0,
input_position: 0,
output: out_array
}
}
#[cfg(feature = "zlib")]
fn write_zlib_header(&mut self)
{
const ZLIB_CM_DEFLATE: u16 = 8;
const ZLIB_CINFO_32K_WINDOW: u16 = 7;
let level_hint = self.options.strategy.to_level();
let mut hdr = (ZLIB_CM_DEFLATE << 8) | (ZLIB_CINFO_32K_WINDOW << 12);
hdr |= u16::from(level_hint) << 6;
hdr |= 31 - (hdr % 31);
self.output[self.output_position..self.output_position + 2]
.copy_from_slice(&hdr.to_be_bytes());
}
fn encode_no_compression(&mut self, bytes: usize)
{
let final_position = self.input_position + bytes;
if self.data.is_empty()
{
self.output[self.output_position] = (1 | (DEFLATE_BLOCKTYPE_UNCOMPRESSED << 1)) as u8;
self.output_position += 1;
let num: u32 = 0xFFFF0000;
self.output[self.output_position..self.output_position + 4]
.copy_from_slice(&num.to_le_bytes());
self.output_position += 4;
return;
}
loop
{
let mut bfinal = 0;
let mut len = usize::from(u16::MAX);
if final_position - self.input_position <= usize::from(u16::MAX)
{
bfinal = 1;
len = final_position - self.input_position;
}
self.output[self.output_position] =
(bfinal | (DEFLATE_BLOCKTYPE_UNCOMPRESSED << 1)) as u8;
self.output_position += 1;
let len_u16 = len as u16;
self.output[self.output_position..self.output_position + 2]
.copy_from_slice(&len_u16.to_le_bytes());
self.output_position += 2;
self.output[self.output_position..self.output_position + 2]
.copy_from_slice(&(!len_u16).to_le_bytes());
self.output_position += 2;
self.output[self.output_position..self.output_position + len]
.copy_from_slice(&self.data[self.input_position..self.input_position + len]);
self.output_position += len;
self.input_position += len;
if self.input_position == final_position
{
break;
}
}
}
pub fn encode_deflate(&mut self)
{
match self.options.strategy
{
DeflateEncodingStrategy::NoCompression =>
{
self.encode_no_compression(self.data.len());
}
}
}
#[cfg(feature = "zlib")]
pub fn encode_zlib(&mut self) -> Vec<u8>
{
let extra = 40 * ((self.data.len() + 41) / 40);
self.output = vec![0_u8; self.data.len() + extra];
self.write_zlib_header();
self.output_position = 2;
self.encode_deflate();
let hash = crate::utils::calc_adler_hash(self.data);
self.output[self.output_position..self.output_position + 4]
.copy_from_slice(&hash.to_be_bytes());
self.output_position += 4;
self.output.truncate(self.output_position);
core::mem::take(&mut self.output)
}
}