use crate::zeck_file_format::error::ZeckFormatError;
use crate::zeck_file_format::{
ZECK_FLAG_BIG_ENDIAN, ZECK_FLAG_RESERVED_MASK, ZECK_FORMAT_VERSION, file::ZeckFile,
};
use crate::{
padless_zeckendorf_decompress_be_dangerous, padless_zeckendorf_decompress_le_dangerous,
};
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn decompress_zeck_file(zeck_file: &ZeckFile) -> Result<Vec<u8>, ZeckFormatError> {
if zeck_file.flags & ZECK_FLAG_RESERVED_MASK != 0 {
return Err(ZeckFormatError::ReservedFlagsSet {
flags: zeck_file.flags,
});
}
match zeck_file.version {
1 => decompress_zeck_v1(
&zeck_file.compressed_data,
zeck_file.original_size,
zeck_file.flags,
),
_ => Err(ZeckFormatError::UnsupportedVersion {
found_version: zeck_file.version,
supported_version: ZECK_FORMAT_VERSION,
}),
}
}
fn decompress_zeck_v1(
compressed_data: &[u8],
original_size: u64,
flags: u8,
) -> Result<Vec<u8>, ZeckFormatError> {
let is_big_endian = (flags & ZECK_FLAG_BIG_ENDIAN) != 0;
let decompressed = if is_big_endian {
padless_zeckendorf_decompress_be_dangerous(compressed_data)
} else {
padless_zeckendorf_decompress_le_dangerous(compressed_data)
};
let original_size_usize = original_size as usize;
let decompressed_len = decompressed.len();
if decompressed_len > original_size_usize {
return Err(ZeckFormatError::DecompressedTooLarge {
expected_size: original_size_usize,
actual_size: decompressed_len,
});
}
if decompressed_len < original_size_usize {
let mut padded = Vec::with_capacity(original_size_usize);
if is_big_endian {
let leading_padding_size = original_size_usize - decompressed_len;
padded.resize(leading_padding_size, 0u8);
padded.extend_from_slice(&decompressed);
} else {
padded.extend_from_slice(&decompressed);
padded.resize(original_size_usize, 0u8);
}
Ok(padded)
} else {
Ok(decompressed)
}
}