use core::mem::zeroed;
use crate::{
consts::BUFFER_MAXIMUM, enet_range_coder_compress, enet_range_coder_create,
enet_range_coder_decompress, enet_range_coder_destroy, ENetBuffer, ENetRangeCoder,
};
pub trait Compressor {
fn compress(&mut self, in_buffers: &[&[u8]], in_limit: usize, out: &mut [u8]) -> usize;
fn decompress(&mut self, in_data: &[u8], out: &mut [u8]) -> usize;
}
pub struct RangeCoder(*mut ENetRangeCoder);
unsafe impl Send for RangeCoder {}
unsafe impl Sync for RangeCoder {}
impl RangeCoder {
#[must_use]
pub fn new() -> Self {
Self(unsafe { enet_range_coder_create().cast() })
}
}
impl Default for RangeCoder {
fn default() -> Self {
RangeCoder::new()
}
}
impl Compressor for RangeCoder {
fn compress(&mut self, in_buffers: &[&[u8]], in_limit: usize, out: &mut [u8]) -> usize {
unsafe {
let mut buffers: [ENetBuffer; BUFFER_MAXIMUM as usize] =
core::array::from_fn(|_| zeroed());
for (i, in_buffer) in in_buffers.iter().enumerate() {
buffers[i] = ENetBuffer {
data: in_buffer.as_ptr().cast_mut(),
data_length: in_buffer.len(),
};
}
enet_range_coder_compress(
self.0.cast(),
buffers.as_ptr(),
in_buffers.len(),
in_limit,
out.as_mut_ptr(),
out.len(),
)
}
}
fn decompress(&mut self, in_data: &[u8], out: &mut [u8]) -> usize {
unsafe {
enet_range_coder_decompress(
self.0.cast(),
in_data.as_ptr(),
in_data.len(),
out.as_mut_ptr(),
out.len(),
)
}
}
}
impl Drop for RangeCoder {
fn drop(&mut self) {
unsafe { enet_range_coder_destroy(self.0.cast::<u8>()) };
}
}