use super::super::{traits::CType, TableUpdateInterval, TableUpdateRate};
use lzham_sys::lzham_decompress_params;
use std::{
ops::BitOr,
os::raw::{c_uint, c_void},
};
#[derive(Clone, Debug)]
pub struct DecompressionOptions {
pub dict_size_log2: u32,
pub table_update_rate: TableUpdateRate,
pub decompression_flags: Option<DecompressionFlag>,
pub num_seed_bytes: Option<u32>,
pub p_seed_bytes: Option<Vec<u8>>,
pub table_update_interval: Option<TableUpdateInterval>,
}
#[derive(Clone, Copy, Debug)]
pub enum DecompressionFlag {
OutputUnbuffered = 1,
ComputeAdler32 = 2,
ReadZlibStream = 4,
}
#[derive(Clone, Copy, Debug)]
pub enum DecompressionStatus {
NotFinished,
HasMoreOutput,
NeedsMoreInput,
Success,
FailedInitialization,
OutputBufferTooSmall,
ExpectedMoreRawBytes,
BadCode,
Adler32,
BadRawBlock,
BadCompBlockSyncCheck,
BadZlibHeader,
NeedSeedBytes,
BadSeedBytes,
BadSyncBlock,
InvalidParameter,
Failed,
}
impl Default for DecompressionOptions {
fn default() -> Self {
Self {
dict_size_log2: 26,
table_update_rate: TableUpdateRate::DEFAULT,
decompression_flags: None,
num_seed_bytes: None,
p_seed_bytes: None,
table_update_interval: None,
}
}
}
impl BitOr for DecompressionFlag {
type Output = Self;
fn bitor(self, _rhs: Self) -> Self {
self
}
}
impl DecompressionStatus {
pub(crate) fn from_c_type(status: lzham_sys::lzham_decompress_status_t) -> Self {
match status {
0 => Self::NotFinished,
1 => DecompressionStatus::HasMoreOutput,
2 => DecompressionStatus::NeedsMoreInput,
3 => DecompressionStatus::Success,
4 => DecompressionStatus::FailedInitialization,
5 => DecompressionStatus::OutputBufferTooSmall,
6 => DecompressionStatus::ExpectedMoreRawBytes,
7 => DecompressionStatus::BadCode,
8 => DecompressionStatus::Adler32,
9 => DecompressionStatus::BadRawBlock,
10 => DecompressionStatus::BadCompBlockSyncCheck,
11 => DecompressionStatus::BadZlibHeader,
12 => DecompressionStatus::NeedSeedBytes,
13 => DecompressionStatus::BadSeedBytes,
14 => DecompressionStatus::BadSyncBlock,
15 => DecompressionStatus::InvalidParameter,
_ => panic!("decomp `status` out of bounds"),
}
}
pub fn is_success(&self) -> bool {
if let Self::Success = self {
true
} else {
false
}
}
pub fn is_success_or_first_failure(&self) -> bool {
*self as u32 >= 3
}
}
impl CType for DecompressionOptions {
type CItem = lzham_decompress_params;
fn to_c_type(self) -> Self::CItem {
let (max, slow) = self.table_update_interval.unwrap_or_default().to_c_type();
lzham_decompress_params {
m_struct_size: std::mem::size_of::<lzham_decompress_params>() as c_uint,
m_dict_size_log2: self.dict_size_log2 as c_uint,
m_table_update_rate: self.table_update_rate.to_c_type(),
m_decompress_flags: self
.decompression_flags
.map_or_else(|| 0, |f| f.to_c_type()),
m_num_seed_bytes: self.num_seed_bytes.unwrap_or(0) as c_uint,
m_pSeed_bytes: {
if let Some(p) = self.p_seed_bytes {
p.as_ptr() as *const c_void
} else {
std::ptr::null()
}
},
m_table_max_update_interval: max,
m_table_update_interval_slow_rate: slow,
}
}
}
impl CType for DecompressionFlag {
type CItem = lzham_sys::lzham_decompress_flags;
fn to_c_type(self) -> Self::CItem {
self as c_uint
}
}
impl CType for DecompressionStatus {
type CItem = lzham_sys::lzham_decompress_status_t;
fn to_c_type(self) -> Self::CItem {
self as c_uint
}
}