diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 17:39:49 +0000 |
commit | a0aa2307322cd47bbf416810ac0292925e03be87 (patch) | |
tree | 37076262a026c4b48c8a0e84f44ff9187556ca35 /rust/vendor/brotli-decompressor/src/ffi | |
parent | Initial commit. (diff) | |
download | suricata-a0aa2307322cd47bbf416810ac0292925e03be87.tar.xz suricata-a0aa2307322cd47bbf416810ac0292925e03be87.zip |
Adding upstream version 1:7.0.3.upstream/1%7.0.3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'rust/vendor/brotli-decompressor/src/ffi')
-rw-r--r-- | rust/vendor/brotli-decompressor/src/ffi/alloc_util.rs | 228 | ||||
-rw-r--r-- | rust/vendor/brotli-decompressor/src/ffi/interface.rs | 49 | ||||
-rw-r--r-- | rust/vendor/brotli-decompressor/src/ffi/mod.rs | 379 |
3 files changed, 656 insertions, 0 deletions
diff --git a/rust/vendor/brotli-decompressor/src/ffi/alloc_util.rs b/rust/vendor/brotli-decompressor/src/ffi/alloc_util.rs new file mode 100644 index 0000000..ee6759a --- /dev/null +++ b/rust/vendor/brotli-decompressor/src/ffi/alloc_util.rs @@ -0,0 +1,228 @@ +use core; +#[cfg(feature="std")] +use std; +use ::alloc; +use super::interface::{c_void, CAllocator}; +#[cfg(feature="std")] +use std::vec::Vec; +#[cfg(feature="std")] +pub use std::boxed::Box; + +#[cfg(feature="std")] +pub struct MemoryBlock<Ty:Sized+Default>(Box<[Ty]>); +#[cfg(feature="std")] +impl<Ty:Sized+Default> Default for MemoryBlock<Ty> { + fn default() -> Self { + MemoryBlock(Vec::<Ty>::new().into_boxed_slice()) + } +} +#[cfg(feature="std")] +impl<Ty:Sized+Default> alloc::SliceWrapper<Ty> for MemoryBlock<Ty> { + fn slice(&self) -> &[Ty] { + &self.0[..] + } +} +#[cfg(feature="std")] +impl<Ty:Sized+Default> alloc::SliceWrapperMut<Ty> for MemoryBlock<Ty> { + fn slice_mut(&mut self) -> &mut [Ty] { + &mut self.0[..] + } +} +#[cfg(feature="std")] +impl<Ty:Sized+Default> core::ops::Index<usize> for MemoryBlock<Ty> { + type Output = Ty; + fn index(&self, index:usize) -> &Ty { + &self.0[index] + } +} +#[cfg(feature="std")] +impl<Ty:Sized+Default> core::ops::IndexMut<usize> for MemoryBlock<Ty> { + + fn index_mut(&mut self, index:usize) -> &mut Ty { + &mut self.0[index] + } +} +#[cfg(feature="std")] +impl<Ty:Sized+Default> Drop for MemoryBlock<Ty> { + fn drop (&mut self) { + if self.0.len() != 0 { + print!("leaking memory block of length {} element size: {}\n", self.0.len(), core::mem::size_of::<Ty>()); + + let to_forget = core::mem::replace(self, MemoryBlock::default()); + core::mem::forget(to_forget);// leak it -- it's the only safe way with custom allocators + } + } +} +pub struct SubclassableAllocator { + alloc: CAllocator + // have alternative ty here +} + +impl SubclassableAllocator { + pub unsafe fn new(sub_alloc:CAllocator) -> Self { + SubclassableAllocator{ + alloc:sub_alloc, + } + } +} +#[cfg(feature="std")] +impl<Ty:Sized+Default+Clone> alloc::Allocator<Ty> for SubclassableAllocator { + type AllocatedMemory = MemoryBlock<Ty>; + fn alloc_cell(&mut self, size:usize) ->MemoryBlock<Ty>{ + if size == 0 { + return MemoryBlock::<Ty>::default(); + } + if let Some(alloc_fn) = self.alloc.alloc_func { + let ptr = alloc_fn(self.alloc.opaque, size * core::mem::size_of::<Ty>()); + let typed_ptr = unsafe {core::mem::transmute::<*mut c_void, *mut Ty>(ptr)}; + let slice_ref = unsafe {super::slice_from_raw_parts_or_nil_mut(typed_ptr, size)}; + for item in slice_ref.iter_mut() { + unsafe{core::ptr::write(item, Ty::default())}; + } + return MemoryBlock(unsafe{Box::from_raw(slice_ref)}) + } + MemoryBlock(vec![Ty::default();size].into_boxed_slice()) + } + fn free_cell(&mut self, mut bv:MemoryBlock<Ty>) { + if (*bv.0).len() != 0 { + if let Some(_) = self.alloc.alloc_func { + let slice_ptr = (*bv.0).as_mut_ptr(); + let _box_ptr = Box::into_raw(core::mem::replace(&mut bv.0, Vec::<Ty>::new().into_boxed_slice())); + if let Some(free_fn) = self.alloc.free_func { + unsafe {free_fn(self.alloc.opaque, core::mem::transmute::<*mut Ty, *mut c_void>(slice_ptr))}; + } + } else { + let _to_free = core::mem::replace(&mut bv.0, Vec::<Ty>::new().into_boxed_slice()); + } + } + } +} + + + + + + + + + + + +#[cfg(not(feature="std"))] +static mut G_SLICE:&'static mut[u8] = &mut[]; +#[cfg(not(feature="std"))] +pub struct MemoryBlock<Ty:Sized+Default>(*mut[Ty]); +#[cfg(not(feature="std"))] +impl<Ty:Sized+Default> Default for MemoryBlock<Ty> { + fn default() -> Self { + MemoryBlock(unsafe{core::mem::transmute::<*mut [u8], *mut[Ty]>(G_SLICE.as_mut())}) + } +} +#[cfg(not(feature="std"))] +impl<Ty:Sized+Default> alloc::SliceWrapper<Ty> for MemoryBlock<Ty> { + fn slice(&self) -> &[Ty] { + if unsafe{(*self.0).len()} == 0 { + &[] + } else { + unsafe{super::slice_from_raw_parts_or_nil(&(*self.0)[0], (*self.0).len())} + } + } +} +#[cfg(not(feature="std"))] +impl<Ty:Sized+Default> alloc::SliceWrapperMut<Ty> for MemoryBlock<Ty> { + fn slice_mut(&mut self) -> &mut [Ty] { + if unsafe{(*self.0).len()} == 0 { + &mut [] + } else { + unsafe{super::slice_from_raw_parts_or_nil_mut(&mut (*self.0)[0], (*self.0).len())} + } + } +} + +#[cfg(not(feature="std"))] +#[cfg(feature="no-stdlib-ffi-binding")] +#[panic_handler] +extern fn panic_impl(_: &::core::panic::PanicInfo) -> ! { + loop {} +} +#[cfg(not(feature="std"))] +#[cfg(feature="no-stdlib-ffi-binding")] +#[lang = "eh_personality"] +extern "C" fn eh_personality() { +} + +#[cfg(not(feature="std"))] +impl<Ty:Sized+Default> core::ops::Index<usize> for MemoryBlock<Ty> { + type Output = Ty; + fn index(&self, index:usize) -> &Ty { + unsafe{&(*self.0)[index]} + } +} +#[cfg(not(feature="std"))] +impl<Ty:Sized+Default> core::ops::IndexMut<usize> for MemoryBlock<Ty> { + + fn index_mut(&mut self, index:usize) -> &mut Ty { + unsafe{&mut (*self.0)[index]} + } +} + +#[cfg(not(feature="std"))] +impl<Ty:Sized+Default+Clone> alloc::Allocator<Ty> for SubclassableAllocator { + type AllocatedMemory = MemoryBlock<Ty>; + fn alloc_cell(&mut self, size:usize) ->MemoryBlock<Ty>{ + if size == 0 { + return MemoryBlock::<Ty>::default(); + } + if let Some(alloc_fn) = self.alloc.alloc_func { + let ptr = alloc_fn(self.alloc.opaque, size * core::mem::size_of::<Ty>()); + let typed_ptr = unsafe {core::mem::transmute::<*mut c_void, *mut Ty>(ptr)}; + let slice_ref = unsafe {super::slice_from_raw_parts_or_nil_mut(typed_ptr, size)}; + for item in slice_ref.iter_mut() { + unsafe{core::ptr::write(item, Ty::default())}; + } + return MemoryBlock(slice_ref.as_mut()) + } else { + panic!("Must provide allocators in no-stdlib code"); + } + } + fn free_cell(&mut self, mut bv:MemoryBlock<Ty>) { + use alloc::SliceWrapper; + use alloc::SliceWrapperMut; + if bv.slice().len() != 0 { + if let Some(_) = self.alloc.alloc_func { + if let Some(free_fn) = self.alloc.free_func { + unsafe {free_fn(self.alloc.opaque, core::mem::transmute::<*mut Ty, *mut c_void>(&mut bv.slice_mut()[0]))}; + } + let _ = core::mem::replace(&mut bv, + MemoryBlock::<Ty>::default()); + } else { + panic!("Must provide allocators in no-stdlib code"); + } + } + } +} + + +#[cfg(not(feature="std"))] +pub fn free_stdlib<T>(_data: *mut T, _size: usize) { + panic!("Must supply allocators if calling divans when compiled with features=no-stdlib"); +} +#[cfg(not(feature="std"))] +pub fn alloc_stdlib<T:Sized+Default+Copy+Clone>(_size: usize) -> *mut T { + panic!("Must supply allocators if calling divans when compiled with features=no-stdlib"); +} + +#[cfg(feature="std")] +pub unsafe fn free_stdlib<T>(ptr: *mut T, size: usize) { + let slice_ref = super::slice_from_raw_parts_or_nil_mut(ptr, size); + let _ = Box::from_raw(slice_ref); // free on drop +} +#[cfg(feature="std")] +pub fn alloc_stdlib<T:Sized+Default+Copy+Clone>(size: usize) -> *mut T { + std::panic::catch_unwind(|| { + let mut newly_allocated = vec![T::default();size].into_boxed_slice(); + let slice_ptr = newly_allocated.as_mut_ptr(); + let _box_ptr = Box::into_raw(newly_allocated); + slice_ptr + }).unwrap_or(core::ptr::null_mut()) +} diff --git a/rust/vendor/brotli-decompressor/src/ffi/interface.rs b/rust/vendor/brotli-decompressor/src/ffi/interface.rs new file mode 100644 index 0000000..eefccac --- /dev/null +++ b/rust/vendor/brotli-decompressor/src/ffi/interface.rs @@ -0,0 +1,49 @@ +use ::BrotliResult; +#[allow(non_camel_case_types)] +#[repr(u8)] +pub enum c_void{ + _Nothing = 0, +} + +#[repr(C)] +#[allow(dead_code)] +pub enum BrotliDecoderParameter { + BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION = 0, + BROTLI_DECODER_PARAM_LARGE_WINDOW = 1, +} + + +#[repr(C)] +pub enum BrotliDecoderResult { + BROTLI_DECODER_RESULT_ERROR = 0, + BROTLI_DECODER_RESULT_SUCCESS = 1, + BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2, + BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3, +} + + +impl From<BrotliResult> for BrotliDecoderResult { + fn from(r: BrotliResult) -> Self { + match r { + BrotliResult::ResultSuccess => BrotliDecoderResult::BROTLI_DECODER_RESULT_SUCCESS, + BrotliResult::ResultFailure => BrotliDecoderResult::BROTLI_DECODER_RESULT_ERROR, + BrotliResult::NeedsMoreInput => BrotliDecoderResult::BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT , + BrotliResult::NeedsMoreOutput => BrotliDecoderResult::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT , + } + } +} +pub type brotli_alloc_func = Option<extern "C" fn(data: *mut c_void, size: usize) -> *mut c_void>; + +pub type brotli_free_func = Option<extern "C" fn(data: *mut c_void, ptr: *mut c_void) -> ()>; + + +#[repr(C)] +#[derive(Clone)] +pub struct CAllocator { + pub alloc_func: brotli_alloc_func, + pub free_func: brotli_free_func, + pub opaque: *mut c_void, +} + +unsafe impl Send for CAllocator { +} diff --git a/rust/vendor/brotli-decompressor/src/ffi/mod.rs b/rust/vendor/brotli-decompressor/src/ffi/mod.rs new file mode 100644 index 0000000..e8f4ae3 --- /dev/null +++ b/rust/vendor/brotli-decompressor/src/ffi/mod.rs @@ -0,0 +1,379 @@ +#![cfg(not(feature="safe"))] + +#[cfg(feature="std")] +use std::{thread,panic, io, boxed, any, string}; +#[cfg(feature="std")] +use std::io::Write; +use core; +use core::slice; +use core::ops; +pub mod interface; +pub mod alloc_util; +use self::alloc_util::SubclassableAllocator; +use alloc::{Allocator, SliceWrapper, SliceWrapperMut, StackAllocator, AllocatedStackMemory, bzero}; +use self::interface::{CAllocator, c_void, BrotliDecoderParameter, BrotliDecoderResult, brotli_alloc_func, brotli_free_func}; +use ::BrotliResult; +use ::BrotliDecoderReturnInfo; +use ::brotli_decode; +pub use ::HuffmanCode; +pub use super::state::{BrotliDecoderErrorCode, BrotliState}; + +pub unsafe fn slice_from_raw_parts_or_nil<'a, T>(data: *const T, len: usize) -> &'a [T] { + if len == 0 { + return &[]; + } + slice::from_raw_parts(data, len) +} + +pub unsafe fn slice_from_raw_parts_or_nil_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T] { + if len == 0 { + return &mut []; + } + slice::from_raw_parts_mut(data, len) +} + +#[cfg(feature="std")] +type BrotliAdditionalErrorData = boxed::Box<dyn any::Any + Send + 'static>; +#[cfg(not(feature="std"))] +type BrotliAdditionalErrorData = (); + +#[repr(C)] +pub struct BrotliDecoderState { + pub custom_allocator: CAllocator, + pub decompressor: ::BrotliState<SubclassableAllocator, + SubclassableAllocator, + SubclassableAllocator>, +} + +#[cfg(not(feature="std"))] +fn brotli_new_decompressor_without_custom_alloc(_to_box: BrotliDecoderState) -> *mut BrotliDecoderState{ + panic!("Must supply allocators if calling divans when compiled without features=std"); +} + +#[cfg(feature="std")] +fn brotli_new_decompressor_without_custom_alloc(to_box: BrotliDecoderState) -> *mut BrotliDecoderState{ + alloc_util::Box::<BrotliDecoderState>::into_raw( + alloc_util::Box::<BrotliDecoderState>::new(to_box)) +} + + +#[no_mangle] +pub unsafe extern fn BrotliDecoderCreateInstance( + alloc_func: brotli_alloc_func, + free_func: brotli_free_func, + opaque: *mut c_void, +) -> *mut BrotliDecoderState { + match catch_panic_state(|| { + let allocators = CAllocator { + alloc_func:alloc_func, + free_func:free_func, + opaque:opaque, + }; + let custom_dictionary = <SubclassableAllocator as Allocator<u8>>::AllocatedMemory::default(); + let to_box = BrotliDecoderState { + custom_allocator: allocators.clone(), + decompressor: ::BrotliState::new_with_custom_dictionary( + SubclassableAllocator::new(allocators.clone()), + SubclassableAllocator::new(allocators.clone()), + SubclassableAllocator::new(allocators.clone()), + custom_dictionary, + ), + }; + if let Some(alloc) = alloc_func { + if free_func.is_none() { + panic!("either both alloc and free must exist or neither"); + } + let ptr = alloc(allocators.opaque, core::mem::size_of::<BrotliDecoderState>()); + let brotli_decoder_state_ptr = core::mem::transmute::<*mut c_void, *mut BrotliDecoderState>(ptr); + core::ptr::write(brotli_decoder_state_ptr, to_box); + brotli_decoder_state_ptr + } else { + brotli_new_decompressor_without_custom_alloc(to_box) + } + }) { + Ok(ret) => ret, + Err(mut e) => { + error_print(core::ptr::null_mut(), &mut e); + core::ptr::null_mut() + }, + } +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderSetParameter(_state_ptr: *mut BrotliDecoderState, + _selector: BrotliDecoderParameter, + _value: u32) { + // not implemented +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderDecompressPrealloc( + encoded_size: usize, + encoded_buffer: *const u8, + decoded_size: usize, + decoded_buffer: *mut u8, + scratch_u8_size: usize, + scratch_u8_buffer: *mut u8, + scratch_u32_size: usize, + scratch_u32_buffer: *mut u32, + scratch_hc_size: usize, + scratch_hc_buffer: *mut HuffmanCode, +) -> BrotliDecoderReturnInfo { + let input = slice_from_raw_parts_or_nil(encoded_buffer, encoded_size); + let output = slice_from_raw_parts_or_nil_mut(decoded_buffer, decoded_size); + let scratch_u8 = slice_from_raw_parts_or_nil_mut(scratch_u8_buffer, scratch_u8_size); + let scratch_u32 = slice_from_raw_parts_or_nil_mut(scratch_u32_buffer, scratch_u32_size); + let scratch_hc = slice_from_raw_parts_or_nil_mut(scratch_hc_buffer, scratch_hc_size); + ::brotli_decode_prealloc(input, output, scratch_u8, scratch_u32, scratch_hc) +} + + +#[no_mangle] +pub unsafe extern fn BrotliDecoderDecompressWithReturnInfo( + encoded_size: usize, + encoded_buffer: *const u8, + decoded_size: usize, + decoded_buffer: *mut u8, +) -> BrotliDecoderReturnInfo { + let input = slice_from_raw_parts_or_nil(encoded_buffer, encoded_size); + let output_scratch = slice_from_raw_parts_or_nil_mut(decoded_buffer, decoded_size); + ::brotli_decode(input, output_scratch) +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderDecompress( + encoded_size: usize, + encoded_buffer: *const u8, + decoded_size: *mut usize, + decoded_buffer: *mut u8, +) -> BrotliDecoderResult { + let res = BrotliDecoderDecompressWithReturnInfo(encoded_size, encoded_buffer, *decoded_size, decoded_buffer); + *decoded_size = res.decoded_size; + match res.result { + BrotliResult::ResultSuccess => BrotliDecoderResult::BROTLI_DECODER_RESULT_SUCCESS, + _ => BrotliDecoderResult::BROTLI_DECODER_RESULT_ERROR + } +} + +#[cfg(all(feature="std", not(feature="pass-through-ffi-panics")))] +fn catch_panic<F:FnOnce()->BrotliDecoderResult+panic::UnwindSafe>(f: F) -> thread::Result<BrotliDecoderResult> { + panic::catch_unwind(f) +} + +#[cfg(all(feature="std", not(feature="pass-through-ffi-panics")))] +fn catch_panic_state<F:FnOnce()->*mut BrotliDecoderState+panic::UnwindSafe>(f: F) -> thread::Result<*mut BrotliDecoderState> { + panic::catch_unwind(f) +} + +#[cfg(all(feature="std", not(feature="pass-through-ffi-panics")))] +unsafe fn error_print(state_ptr: *mut BrotliDecoderState, err: &mut BrotliAdditionalErrorData) { + if let Some(st) = err.downcast_ref::<&str>() { + if !state_ptr.is_null() { + let mut str_cpy = [0u8;256]; + let src:&[u8] = st.as_ref(); + let xlen = core::cmp::min(src.len(), str_cpy.len() - 1); + str_cpy.split_at_mut(xlen).0.clone_from_slice( + src.split_at(xlen).0); + str_cpy[xlen] = 0; // null terminate + (*state_ptr).decompressor.mtf_or_error_string = Err(str_cpy); + } + let _ign = writeln!(&mut io::stderr(), "panic: {}", st); + } else { + if let Some(st) = err.downcast_ref::<string::String>() { + + if !state_ptr.is_null() { + let mut str_cpy = [0u8;256]; + let src: &[u8] = st.as_ref(); + let xlen = core::cmp::min(src.len(), str_cpy.len() - 1); + str_cpy.split_at_mut(xlen).0.clone_from_slice( + src.split_at(xlen).0); + str_cpy[xlen] = 0; // null terminate + (*state_ptr).decompressor.mtf_or_error_string = Err(str_cpy); + } + let _ign = writeln!(&mut io::stderr(), "Internal Error {:?}", st); + } else { + let _ign = writeln!(&mut io::stderr(), "Internal Error {:?}", err); + } + } +} + +// can't catch panics in a reliable way without std:: configure with panic=abort. These shouldn't happen +#[cfg(any(not(feature="std"), feature="pass-through-ffi-panics"))] +fn catch_panic<F:FnOnce()->BrotliDecoderResult>(f: F) -> Result<BrotliDecoderResult, BrotliAdditionalErrorData> { + Ok(f()) +} + +#[cfg(any(not(feature="std"), feature="pass-through-ffi-panics"))] +fn catch_panic_state<F:FnOnce()->*mut BrotliDecoderState>(f: F) -> Result<*mut BrotliDecoderState, BrotliAdditionalErrorData> { + Ok(f()) +} + +#[cfg(any(not(feature="std"), feature="pass-through-ffi-panics"))] +fn error_print(_state_ptr: *mut BrotliDecoderState, _err: &mut BrotliAdditionalErrorData) { +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderDecompressStream( + state_ptr: *mut BrotliDecoderState, + available_in: *mut usize, + input_buf_ptr: *mut*const u8, + available_out: *mut usize, + output_buf_ptr: *mut*mut u8, + mut total_out: *mut usize) -> BrotliDecoderResult { + match catch_panic(move || { + let mut input_offset = 0usize; + let mut output_offset = 0usize; + let mut fallback_total_out = 0usize; + if total_out.is_null() { + total_out = &mut fallback_total_out; + } + let result: BrotliDecoderResult; + { + let input_buf = slice_from_raw_parts_or_nil(*input_buf_ptr, *available_in); + let output_buf = slice_from_raw_parts_or_nil_mut(*output_buf_ptr, *available_out); + result = super::decode::BrotliDecompressStream( + &mut *available_in, + &mut input_offset, + input_buf, + &mut *available_out, + &mut output_offset, + output_buf, + &mut *total_out, + &mut (*state_ptr).decompressor, + ).into(); + } + *input_buf_ptr = (*input_buf_ptr).offset(input_offset as isize); + *output_buf_ptr = (*output_buf_ptr).offset(output_offset as isize); + result + }) { + Ok(ret) => ret, + Err(mut readable_err) => { // if we panic (completely unexpected) then we should report it back to C and print + error_print(state_ptr, &mut readable_err); + (*state_ptr).decompressor.error_code = BrotliDecoderErrorCode::BROTLI_DECODER_ERROR_UNREACHABLE; + BrotliDecoderResult::BROTLI_DECODER_RESULT_ERROR + } + } +} + +/// Equivalent to BrotliDecoderDecompressStream but with no optional arg and no double indirect ptrs +#[no_mangle] +pub unsafe extern fn BrotliDecoderDecompressStreaming( + state_ptr: *mut BrotliDecoderState, + available_in: *mut usize, + mut input_buf_ptr: *const u8, + available_out: *mut usize, + mut output_buf_ptr: *mut u8) -> BrotliDecoderResult { + BrotliDecoderDecompressStream(state_ptr, + available_in, + &mut input_buf_ptr, + available_out, + &mut output_buf_ptr, + core::ptr::null_mut()) +} + +#[cfg(feature="std")] +unsafe fn free_decompressor_no_custom_alloc(state_ptr: *mut BrotliDecoderState) { + let _state = alloc_util::Box::from_raw(state_ptr); +} + +#[cfg(not(feature="std"))] +unsafe fn free_decompressor_no_custom_alloc(_state_ptr: *mut BrotliDecoderState) { + unreachable!(); +} + + +#[no_mangle] +pub unsafe extern fn BrotliDecoderMallocU8(state_ptr: *mut BrotliDecoderState, size: usize) -> *mut u8 { + if let Some(alloc_fn) = (*state_ptr).custom_allocator.alloc_func { + return core::mem::transmute::<*mut c_void, *mut u8>(alloc_fn((*state_ptr).custom_allocator.opaque, size)); + } else { + return alloc_util::alloc_stdlib(size); + } +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderFreeU8(state_ptr: *mut BrotliDecoderState, data: *mut u8, size: usize) { + if let Some(free_fn) = (*state_ptr).custom_allocator.free_func { + free_fn((*state_ptr).custom_allocator.opaque, core::mem::transmute::<*mut u8, *mut c_void>(data)); + } else { + alloc_util::free_stdlib(data, size); + } +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderMallocUsize(state_ptr: *mut BrotliDecoderState, size: usize) -> *mut usize { + if let Some(alloc_fn) = (*state_ptr).custom_allocator.alloc_func { + return core::mem::transmute::<*mut c_void, *mut usize>(alloc_fn((*state_ptr).custom_allocator.opaque, + size * core::mem::size_of::<usize>())); + } else { + return alloc_util::alloc_stdlib(size); + } +} +#[no_mangle] +pub unsafe extern fn BrotliDecoderFreeUsize(state_ptr: *mut BrotliDecoderState, data: *mut usize, size: usize) { + if let Some(free_fn) = (*state_ptr).custom_allocator.free_func { + free_fn((*state_ptr).custom_allocator.opaque, core::mem::transmute::<*mut usize, *mut c_void>(data)); + } else { + alloc_util::free_stdlib(data, size); + } +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderDestroyInstance(state_ptr: *mut BrotliDecoderState) { + if let Some(_) = (*state_ptr).custom_allocator.alloc_func { + if let Some(free_fn) = (*state_ptr).custom_allocator.free_func { + let _to_free = core::ptr::read(state_ptr); + let ptr = core::mem::transmute::<*mut BrotliDecoderState, *mut c_void>(state_ptr); + free_fn((*state_ptr).custom_allocator.opaque, ptr); + } + } else { + free_decompressor_no_custom_alloc(state_ptr); + } +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderHasMoreOutput(state_ptr: *const BrotliDecoderState) -> i32 { + if super::decode::BrotliDecoderHasMoreOutput(&(*state_ptr).decompressor) {1} else {0} +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderTakeOutput(state_ptr: *mut BrotliDecoderState, size: *mut usize) -> *const u8 { + super::decode::BrotliDecoderTakeOutput(&mut (*state_ptr).decompressor, &mut *size).as_ptr() +} + + + +#[no_mangle] +pub unsafe extern fn BrotliDecoderIsUsed(state_ptr: *const BrotliDecoderState) -> i32 { + if super::decode::BrotliDecoderIsUsed(&(*state_ptr).decompressor) {1} else {0} +} +#[no_mangle] +pub unsafe extern fn BrotliDecoderIsFinished(state_ptr: *const BrotliDecoderState) -> i32 { + if super::decode::BrotliDecoderIsFinished(&(*state_ptr).decompressor) {1} else {0} +} +#[no_mangle] +pub unsafe extern fn BrotliDecoderGetErrorCode(state_ptr: *const BrotliDecoderState) -> BrotliDecoderErrorCode { + super::decode::BrotliDecoderGetErrorCode(&(*state_ptr).decompressor) +} + +#[no_mangle] +pub unsafe extern fn BrotliDecoderGetErrorString(state_ptr: *const BrotliDecoderState) -> *const u8 { + if !state_ptr.is_null() { + if let &Err(ref msg) = &(*state_ptr).decompressor.mtf_or_error_string { + // important: this must be a ref + // so stack memory is not returned + return msg.as_ptr(); + } + } + BrotliDecoderErrorString(super::decode::BrotliDecoderGetErrorCode(&(*state_ptr).decompressor)) +} +#[no_mangle] +pub extern fn BrotliDecoderErrorString(c: BrotliDecoderErrorCode) -> *const u8 { + ::state::BrotliDecoderErrorStr(c).as_ptr() +} + + +#[no_mangle] +pub extern fn BrotliDecoderVersion() -> u32 { + 0x1000f00 +} |