#[cfg(test)]
mod tests;
use oodle_sys;
include!("constants.rs");
pub enum Compressor {
None,
Kraken,
Leviathan,
Mermaid,
Selkie,
Hydra,
}
impl Into<oodle_sys::OodleLZ_Compressor> for Compressor {
fn into(self) -> oodle_sys::OodleLZ_Compressor {
match self {
Compressor::None => oodle_sys::OodleLZ_Compressor_OodleLZ_Compressor_None,
Compressor::Kraken => oodle_sys::OodleLZ_Compressor_OodleLZ_Compressor_Kraken,
Compressor::Leviathan => oodle_sys::OodleLZ_Compressor_OodleLZ_Compressor_Leviathan,
Compressor::Mermaid => oodle_sys::OodleLZ_Compressor_OodleLZ_Compressor_Mermaid,
Compressor::Selkie => oodle_sys::OodleLZ_Compressor_OodleLZ_Compressor_Selkie,
Compressor::Hydra => oodle_sys::OodleLZ_Compressor_OodleLZ_Compressor_Hydra,
}
}
}
pub enum CompressionLevel {
None,
SuperFast,
VeryFast,
Fast,
Normal,
Optimal1,
Optimal2,
Optimal3,
Optimal4,
Optimal5,
HyperFast1,
HyperFast2,
HyperFast3,
HyperFast4,
Optimal,
HyperFast,
Max,
Min,
}
impl Into<oodle_sys::OodleLZ_CompressionLevel> for CompressionLevel {
#[rustfmt::skip]
fn into(self) -> oodle_sys::OodleLZ_CompressionLevel {
match self {
CompressionLevel::None => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_None,
CompressionLevel::SuperFast => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_SuperFast,
CompressionLevel::VeryFast => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_VeryFast,
CompressionLevel::Fast => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Fast,
CompressionLevel::Normal => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Normal,
CompressionLevel::Optimal1 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Optimal1,
CompressionLevel::Optimal2 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Optimal2,
CompressionLevel::Optimal3 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Optimal3,
CompressionLevel::Optimal4 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Optimal4,
CompressionLevel::Optimal5 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Optimal5,
CompressionLevel::HyperFast1 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_HyperFast1,
CompressionLevel::HyperFast2 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_HyperFast2,
CompressionLevel::HyperFast3 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_HyperFast3,
CompressionLevel::HyperFast4 => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_HyperFast4,
CompressionLevel::Optimal => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Optimal,
CompressionLevel::HyperFast => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_HyperFast,
CompressionLevel::Max => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Max,
CompressionLevel::Min => oodle_sys::OodleLZ_CompressionLevel_OodleLZ_CompressionLevel_Min,
}
}
}
impl Default for CompressionLevel {
fn default() -> Self {
CompressionLevel::Normal
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Profile {
Main,
Reduced,
}
impl Into<oodle_sys::OodleLZ_Profile> for Profile {
fn into(self) -> oodle_sys::OodleLZ_Profile {
match self {
Profile::Main => oodle_sys::OodleLZ_Profile_OodleLZ_Profile_Main,
Profile::Reduced => oodle_sys::OodleLZ_Profile_OodleLZ_Profile_Reduced,
}
}
}
impl From<oodle_sys::OodleLZ_Profile> for Profile {
fn from(profile: oodle_sys::OodleLZ_Profile) -> Self {
match profile {
oodle_sys::OodleLZ_Profile_OodleLZ_Profile_Main => Profile::Main,
oodle_sys::OodleLZ_Profile_OodleLZ_Profile_Reduced => Profile::Reduced,
_ => panic!("Invalid profile"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Jobify {
Default,
Disable,
Normal,
Aggressive,
}
impl Into<oodle_sys::OodleLZ_Jobify> for Jobify {
fn into(self) -> oodle_sys::OodleLZ_Jobify {
match self {
Jobify::Default => oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Default,
Jobify::Disable => oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Disable,
Jobify::Normal => oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Normal,
Jobify::Aggressive => oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Aggressive,
}
}
}
impl From<oodle_sys::OodleLZ_Jobify> for Jobify {
fn from(jobify: oodle_sys::OodleLZ_Jobify) -> Self {
match jobify {
oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Default => Jobify::Default,
oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Disable => Jobify::Disable,
oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Normal => Jobify::Normal,
oodle_sys::OodleLZ_Jobify_OodleLZ_Jobify_Aggressive => Jobify::Aggressive,
_ => panic!("Invalid jobify"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct CompressOptions {
unused: u32,
min_match_len: i32,
seek_chunk_reset: bool,
seek_chunk_len: u32,
profile: Profile,
dictionary_size: i32,
space_speed_tradeoff_bytes: i32,
unused2: i32,
send_quantum_crcs: bool,
max_local_dictionary_size: u32,
make_long_range_matcher: bool,
match_table_size_log2: i32,
jobify: Jobify,
jobify_user_ptr: *mut std::ffi::c_void,
far_match_min_len: i32,
far_match_offset_log2: i32,
reserved: [u32; 4],
}
impl CompressOptions {
pub fn validate(&mut self) {
let options: *mut oodle_sys::OodleLZ_CompressOptions = &mut (*self).into();
unsafe { oodle_sys::OodleLZ_CompressOptions_Validate(options) };
*self = CompressOptions::from(unsafe { *options });
}
}
impl Into<oodle_sys::OodleLZ_CompressOptions> for CompressOptions {
fn into(self) -> oodle_sys::OodleLZ_CompressOptions {
oodle_sys::OodleLZ_CompressOptions {
unused_was_verbosity: self.unused,
minMatchLen: self.min_match_len,
seekChunkReset: if self.seek_chunk_reset { 1 } else { 0 },
seekChunkLen: self.seek_chunk_len as i32,
profile: self.profile.into(),
dictionarySize: self.dictionary_size,
spaceSpeedTradeoffBytes: self.space_speed_tradeoff_bytes,
unused_was_maxHuffmansPerChunk: self.unused2,
sendQuantumCRCs: if self.send_quantum_crcs { 1 } else { 0 },
maxLocalDictionarySize: self.max_local_dictionary_size as i32,
makeLongRangeMatcher: if self.make_long_range_matcher { 1 } else { 0 },
matchTableSizeLog2: self.match_table_size_log2,
jobify: self.jobify.into(),
jobifyUserPtr: self.jobify_user_ptr,
farMatchMinLen: self.far_match_min_len,
farMatchOffsetLog2: self.far_match_offset_log2,
reserved: self.reserved,
}
}
}
impl From<oodle_sys::OodleLZ_CompressOptions> for CompressOptions {
fn from(options: oodle_sys::OodleLZ_CompressOptions) -> Self {
Self {
unused: options.unused_was_verbosity,
min_match_len: options.minMatchLen,
seek_chunk_reset: options.seekChunkReset != 0,
seek_chunk_len: options.seekChunkLen as u32,
profile: options.profile.into(),
dictionary_size: options.dictionarySize,
space_speed_tradeoff_bytes: options.spaceSpeedTradeoffBytes,
unused2: options.unused_was_maxHuffmansPerChunk,
send_quantum_crcs: options.sendQuantumCRCs != 0,
max_local_dictionary_size: options.maxLocalDictionarySize as u32,
make_long_range_matcher: options.makeLongRangeMatcher != 0,
match_table_size_log2: options.matchTableSizeLog2,
jobify: options.jobify.into(),
jobify_user_ptr: options.jobifyUserPtr,
far_match_min_len: options.farMatchMinLen,
far_match_offset_log2: options.farMatchOffsetLog2,
reserved: options.reserved,
}
}
}
impl Default for CompressOptions {
fn default() -> Self {
let options = unsafe {
*oodle_sys::OodleLZ_CompressOptions_GetDefault(
Compressor::None.into(),
CompressionLevel::None.into(),
)
};
options.into()
}
}
pub fn compress(
compressor: Compressor,
decompressed: &[u8],
compressed: &mut [u8],
level: CompressionLevel,
options: Option<CompressOptions>,
dictionary_base: Option<&[u8]>,
scratch_memory: Option<&mut [u8]>,
) -> Result<usize, u32> {
let options = match options {
Some(x) => &x.into(),
None => std::ptr::null() as *const _,
};
let dictionary_base = match dictionary_base {
Some(x) => x.as_ptr(),
None => std::ptr::null(),
};
let (scratch_memory, scratch_memory_len) = match scratch_memory {
Some(x) => (x.as_mut_ptr(), x.len() as isize),
None => (std::ptr::null_mut(), 0),
};
let result = unsafe {
oodle_sys::OodleLZ_Compress(
compressor.into(),
decompressed.as_ptr() as *const _,
decompressed.len() as isize,
compressed.as_mut_ptr() as *mut _,
level.into(),
options,
dictionary_base as *const _,
std::ptr::null(), scratch_memory as *mut _,
scratch_memory_len,
) as usize
};
if result == FAILED as usize {
Err(FAILED)
} else {
let compressed_data = compressed[..result].to_vec();
compressed[..result].copy_from_slice(&compressed_data);
Ok(result)
}
}
pub enum CheckCRC {
No,
Yes,
}
impl Default for CheckCRC {
fn default() -> Self {
CheckCRC::No
}
}
impl Into<oodle_sys::OodleLZ_CheckCRC> for CheckCRC {
fn into(self) -> oodle_sys::OodleLZ_CheckCRC {
match self {
CheckCRC::No => oodle_sys::OodleLZ_CheckCRC_OodleLZ_CheckCRC_No,
CheckCRC::Yes => oodle_sys::OodleLZ_CheckCRC_OodleLZ_CheckCRC_Yes,
}
}
}
pub enum Verbosity {
None,
Minimal,
Some,
Lots,
}
impl Default for Verbosity {
fn default() -> Self {
Verbosity::None
}
}
impl Into<oodle_sys::OodleLZ_Verbosity> for Verbosity {
fn into(self) -> oodle_sys::OodleLZ_Verbosity {
match self {
Verbosity::None => oodle_sys::OodleLZ_Verbosity_OodleLZ_Verbosity_None,
Verbosity::Minimal => oodle_sys::OodleLZ_Verbosity_OodleLZ_Verbosity_Minimal,
Verbosity::Some => oodle_sys::OodleLZ_Verbosity_OodleLZ_Verbosity_Some,
Verbosity::Lots => oodle_sys::OodleLZ_Verbosity_OodleLZ_Verbosity_Lots,
}
}
}
pub enum DecodeThreadPhase {
One,
Two,
All,
Unthreaded,
}
impl Default for DecodeThreadPhase {
fn default() -> Self {
DecodeThreadPhase::Unthreaded
}
}
impl Into<oodle_sys::OodleLZ_Decode_ThreadPhase> for DecodeThreadPhase {
#[rustfmt::skip]
fn into(self) -> oodle_sys::OodleLZ_Decode_ThreadPhase {
match self {
DecodeThreadPhase::One => oodle_sys::OodleLZ_Decode_ThreadPhase_OodleLZ_Decode_ThreadPhase1,
DecodeThreadPhase::Two => oodle_sys::OodleLZ_Decode_ThreadPhase_OodleLZ_Decode_ThreadPhase2,
DecodeThreadPhase::All => oodle_sys::OodleLZ_Decode_ThreadPhase_OodleLZ_Decode_ThreadPhaseAll,
DecodeThreadPhase::Unthreaded => oodle_sys::OodleLZ_Decode_ThreadPhase_OodleLZ_Decode_Unthreaded,
}
}
}
pub fn decompress(
compressed: &[u8],
decompressed: &mut [u8],
dictionary_base: Option<&mut [u8]>,
check_crc: Option<CheckCRC>,
verbosity: Option<Verbosity>,
thread_phase: Option<DecodeThreadPhase>,
) -> Result<usize, u32> {
let (dictionary_base, dictionary_base_len) = match dictionary_base {
Some(x) => (x.as_mut_ptr(), x.len() as isize),
None => (std::ptr::null_mut(), 0),
};
let result = unsafe {
oodle_sys::OodleLZ_Decompress(
compressed.as_ptr() as *const _,
compressed.len() as isize,
decompressed.as_mut_ptr() as *mut _,
decompressed.len() as isize,
oodle_sys::OodleLZ_FuzzSafe_OodleLZ_FuzzSafe_Yes,
check_crc.unwrap_or_default().into(),
verbosity.unwrap_or_default().into(),
dictionary_base as *mut _,
dictionary_base_len,
None, std::ptr::null_mut(),
std::ptr::null_mut(),
0,
thread_phase.unwrap_or_default().into(),
) as usize
};
if result == FAILED as usize {
Err(FAILED)
} else {
Ok(result)
}
}