use core::ffi::{c_uint, c_void};
extern crate alloc;
use alloc::alloc::Layout;
pub use alloc::boxed::Box;
use core::{mem, ptr};
#[cfg(not(any(target_os = "macos", all(windows, target_pointer_width = "64"))))]
const MIN_ALIGN: usize = 8;
#[cfg(any(target_os = "macos", all(windows, target_pointer_width = "64")))]
const MIN_ALIGN: usize = 16;
const LAYOUT_OFFSET: usize = mem::size_of::<usize>();
#[cold]
#[inline(never)]
fn unlikely_null() -> *mut c_void {
ptr::null_mut()
}
#[inline]
pub unsafe extern "C" fn compu_malloc(size: usize) -> *mut c_void {
if let Ok(layout) = Layout::from_size_align(size + LAYOUT_OFFSET, MIN_ALIGN) {
let mem = alloc::alloc::alloc(layout);
if !mem.is_null() {
ptr::write(mem as *mut usize, size);
return mem.add(LAYOUT_OFFSET) as _;
}
}
unlikely_null()
}
#[inline]
pub unsafe extern "C" fn compu_free(mem: *mut c_void) {
if !mem.is_null() {
let mem = (mem as *mut u8).offset(-(LAYOUT_OFFSET as isize));
let size = ptr::read(mem as *const usize);
let layout = Layout::from_size_align_unchecked(size + LAYOUT_OFFSET, MIN_ALIGN);
alloc::alloc::dealloc(mem, layout);
}
}
#[allow(unused)]
pub(crate) unsafe extern "C" fn compu_malloc_with_state(
_: *mut c_void,
size: usize,
) -> *mut c_void {
compu_malloc(size)
}
#[allow(unused)]
pub(crate) unsafe extern "C" fn compu_alloc(
_: *mut c_void,
items: c_uint,
size: c_uint,
) -> *mut c_void {
let size = match (items as usize).checked_mul(size as usize) {
Some(0) | None => return unlikely_null(),
Some(size) => size,
};
compu_malloc(size)
}
#[allow(unused)]
pub(crate) unsafe extern "C" fn compu_free_with_state(_: *mut c_void, mem: *mut c_void) {
compu_free(mem)
}
#[cfg(feature = "brotli-rust")]
pub mod brotli_rust {
extern crate alloc;
use super::Box;
use alloc::vec::Vec;
pub struct BoxedSlice<T>(Box<[T]>);
impl<T> Default for BoxedSlice<T> {
#[inline(always)]
fn default() -> Self {
Self(Vec::new().into_boxed_slice())
}
}
impl<T> brotli::SliceWrapper<T> for BoxedSlice<T> {
#[inline(always)]
fn slice(&self) -> &[T] {
&self.0
}
}
impl<T> brotli::SliceWrapperMut<T> for BoxedSlice<T> {
#[inline(always)]
fn slice_mut(&mut self) -> &mut [T] {
&mut self.0
}
}
#[derive(Copy, Clone, Default)]
pub struct BrotliAllocator;
impl<T: Default> brotli::Allocator<T> for BrotliAllocator {
type AllocatedMemory = BoxedSlice<T>;
fn alloc_cell(&mut self, len: usize) -> Self::AllocatedMemory {
let mut vec = Vec::with_capacity(len);
for _ in 0..len {
vec.push(Default::default());
}
BoxedSlice(vec.into_boxed_slice())
}
fn free_cell(&mut self, _data: Self::AllocatedMemory) {}
}
impl brotli::enc::BrotliAlloc for BrotliAllocator {}
}