use crate::zeck_file_format::{
ZECK_FLAG_BIG_ENDIAN, ZECK_FORMAT_VERSION, ZECK_HEADER_SIZE, error::ZeckFormatError,
};
use serde::{Deserialize, Serialize};
use tsify::Tsify;
use wasm_bindgen::prelude::*;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Tsify)]
#[tsify(into_wasm_abi, from_wasm_abi)]
pub struct ZeckFile {
pub version: u8,
pub original_size: u64,
pub flags: u8,
pub compressed_data: Vec<u8>,
}
impl ZeckFile {
pub(crate) fn new(original_size: u64, compressed_data: Vec<u8>, is_big_endian: bool) -> Self {
let mut flags = 0u8;
if is_big_endian {
flags |= ZECK_FLAG_BIG_ENDIAN;
}
Self {
version: ZECK_FORMAT_VERSION,
original_size,
flags,
compressed_data,
}
}
pub fn is_big_endian(&self) -> bool {
(self.flags & ZECK_FLAG_BIG_ENDIAN) != 0
}
pub fn to_bytes(&self) -> Vec<u8> {
let mut output = Vec::with_capacity(ZECK_HEADER_SIZE + self.compressed_data.len());
output.push(self.version);
output.extend_from_slice(&self.original_size.to_le_bytes());
output.push(self.flags);
output.extend_from_slice(&self.compressed_data);
output
}
pub fn total_size(&self) -> usize {
ZECK_HEADER_SIZE + self.compressed_data.len()
}
}
#[wasm_bindgen]
pub fn zeck_file_is_big_endian(zeck_file: &ZeckFile) -> bool {
zeck_file.is_big_endian()
}
#[wasm_bindgen]
pub fn zeck_file_to_bytes(zeck_file: &ZeckFile) -> Vec<u8> {
zeck_file.to_bytes()
}
#[wasm_bindgen]
pub fn zeck_file_total_size(zeck_file: &ZeckFile) -> usize {
zeck_file.total_size()
}
impl std::fmt::Display for ZeckFile {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"ZeckFile {{ version: {}, original_size: {} bytes, compressed_size: {} bytes, endianness: {} }}",
self.version,
self.original_size,
self.compressed_data.len(),
if self.is_big_endian() {
"big"
} else {
"little"
}
)
}
}
#[wasm_bindgen]
pub fn deserialize_zeck_file(zeck_file_data: &[u8]) -> Result<ZeckFile, ZeckFormatError> {
if zeck_file_data.len() < ZECK_HEADER_SIZE {
return Err(ZeckFormatError::HeaderTooShort {
actual_length: zeck_file_data.len(),
required_length: ZECK_HEADER_SIZE,
});
}
let version = zeck_file_data[0];
let original_size = u64::from_le_bytes([
zeck_file_data[1],
zeck_file_data[2],
zeck_file_data[3],
zeck_file_data[4],
zeck_file_data[5],
zeck_file_data[6],
zeck_file_data[7],
zeck_file_data[8],
]);
let flags = zeck_file_data[9];
let compressed_data = zeck_file_data[ZECK_HEADER_SIZE..].to_vec();
Ok(ZeckFile {
version,
original_size,
flags,
compressed_data,
})
}