use alloc::{boxed::Box, vec, vec::Vec};
use core::error::Error;
use crate::WuffErr;
use crate::decompress_woff2_with_custom_brotli;
struct Rebox<T>(Box<[T]>);
impl<T> Default for Rebox<T> {
fn default() -> Self {
Rebox(Vec::new().into_boxed_slice())
}
}
impl<T> brotli_decompressor::SliceWrapper<T> for Rebox<T> {
fn slice(&self) -> &[T] {
&self.0
}
}
impl<T> brotli_decompressor::SliceWrapperMut<T> for Rebox<T> {
fn slice_mut(&mut self) -> &mut [T] {
&mut self.0
}
}
struct HeapAlloc;
impl<T: Clone + Default> brotli_decompressor::Allocator<T> for HeapAlloc {
type AllocatedMemory = Rebox<T>;
fn alloc_cell(&mut self, len: usize) -> Rebox<T> {
Rebox(vec![T::default(); len].into_boxed_slice())
}
fn free_cell(&mut self, _data: Rebox<T>) {}
}
fn decompress_brotli(
compressed_data: &[u8],
expected_size: usize,
) -> Result<Vec<u8>, Box<dyn Error>> {
use brotli_decompressor::{BrotliDecompressStream, BrotliResult, BrotliState};
let mut output = vec![0u8; expected_size];
let mut available_in = compressed_data.len();
let mut input_offset = 0usize;
let mut available_out = output.len();
let mut output_offset = 0usize;
let mut total_out = 0usize;
let mut state = BrotliState::new(HeapAlloc, HeapAlloc, HeapAlloc);
let result = BrotliDecompressStream(
&mut available_in,
&mut input_offset,
compressed_data,
&mut available_out,
&mut output_offset,
&mut output,
&mut total_out,
&mut state,
);
if !matches!(result, BrotliResult::ResultSuccess) || output_offset != expected_size {
return Err(Box::new(WuffErr::GenericError));
}
Ok(output)
}
pub fn decompress_woff2(raw_woff_data: &[u8]) -> Result<Vec<u8>, WuffErr> {
decompress_woff2_with_custom_brotli(raw_woff_data, &mut decompress_brotli)
}