use crate::error::Base64Error;
use crate::{databuf::DataBuf, error::CompressionError, ffi};
use std::{ffi::CString, mem::MaybeUninit, path::Path};
pub fn compress_data(data: &[u8]) -> Result<DataBuf<[u8]>, CompressionError> {
let mut out_length = MaybeUninit::uninit();
let buffer = {
unsafe {
ffi::CompressData(
data.as_ptr() as *mut _,
data.len() as i32,
out_length.as_mut_ptr(),
)
}
};
if !buffer.is_null() && unsafe { out_length.assume_init() } < 1 {
unsafe { ffi::MemFree(buffer.cast()) };
return Err(CompressionError::CompressionFailed);
}
unsafe { DataBuf::slice_from_raw(buffer, out_length) }
.ok_or(CompressionError::CompressionFailed)
}
pub fn decompress_data(data: &[u8]) -> Result<DataBuf<[u8]>, CompressionError> {
let mut out_length = MaybeUninit::uninit();
let buffer = {
unsafe {
ffi::DecompressData(
data.as_ptr() as *mut _,
data.len() as i32,
out_length.as_mut_ptr(),
)
}
};
if !buffer.is_null() && unsafe { out_length.assume_init() } < 1 {
unsafe { ffi::MemFree(buffer.cast()) };
return Err(CompressionError::CompressionFailed);
}
unsafe { DataBuf::slice_from_raw(buffer, out_length) }
.ok_or(CompressionError::CompressionFailed)
}
#[cfg(unix)]
fn path_to_bytes<P: AsRef<Path>>(path: P) -> Vec<u8> {
use std::os::unix::ffi::OsStrExt;
path.as_ref().as_os_str().as_bytes().to_vec()
}
#[cfg(not(unix))]
fn path_to_bytes<P: AsRef<Path>>(path: P) -> Vec<u8> {
path.as_ref().to_string_lossy().to_string().into_bytes()
}
pub fn export_data_as_code(data: &[u8], file_name: impl AsRef<Path>) -> bool {
let c_str = CString::new(path_to_bytes(file_name)).unwrap();
unsafe { ffi::ExportDataAsCode(data.as_ptr(), data.len() as i32, c_str.as_ptr()) }
}
pub fn encode_data_base64(data: &[u8]) -> Result<DataBuf<[u8]>, Base64Error> {
let mut output_size = MaybeUninit::<i32>::uninit();
let bytes = unsafe {
ffi::EncodeDataBase64(data.as_ptr(), data.len() as i32, output_size.as_mut_ptr())
};
unsafe { DataBuf::slice_from_raw(bytes as *mut u8, output_size) }
.ok_or(Base64Error::EncodeFailed)
}
pub fn decode_data_base64(data: &[u8]) -> Result<DataBuf<[u8]>, Base64Error> {
let mut output_size = MaybeUninit::<i32>::uninit();
let null_trimmed_data = match data.iter().position(|&element| element == 0) {
Some(pos) => &data[..pos],
None => data,
};
if null_trimmed_data.is_empty() || null_trimmed_data.iter().all(|&b| b == b'=') {
return Err(Base64Error::DecodeFailed);
}
let mut c_str = Vec::with_capacity(null_trimmed_data.len() + 1);
c_str.extend_from_slice(null_trimmed_data);
c_str.push(0);
let bytes = unsafe {
ffi::DecodeDataBase64(
c_str.as_ptr() as *const ::std::os::raw::c_char,
output_size.as_mut_ptr(),
)
};
if !bytes.is_null() && unsafe { output_size.assume_init() } < 1 {
unsafe { ffi::MemFree(bytes.cast()) };
return Err(Base64Error::DecodeFailed);
}
unsafe { DataBuf::slice_from_raw(bytes, output_size) }.ok_or(Base64Error::DecodeFailed)
}