#![no_std]
#![allow(non_snake_case)]
#![allow(unused_parens)]
#![allow(unused_imports)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![cfg_attr(feature="no-stdlib-ffi-binding",cfg_attr(not(feature="std"), feature(lang_items)))]
#![cfg_attr(feature="no-stdlib-ffi-binding",cfg_attr(not(feature="std"), feature(panic_handler)))]
#[macro_use]
#[cfg(feature="std")]
extern crate std;
#[cfg(feature="std")]
use std::io::{self, Error, ErrorKind, Read, Write};
#[cfg(feature="std")]
extern crate alloc_stdlib;
#[macro_use]
extern crate alloc_no_stdlib as alloc;
pub use alloc::{AllocatedStackMemory, Allocator, SliceWrapper, SliceWrapperMut, StackAllocator, bzero};
use core::ops;
#[cfg(feature="std")]
pub use alloc_stdlib::StandardAlloc;
#[cfg(all(feature="unsafe",feature="std"))]
pub use alloc_stdlib::HeapAlloc;
#[macro_use]
mod memory;
pub mod dictionary;
mod brotli_alloc;
#[macro_use]
mod bit_reader;
mod huffman;
mod state;
mod prefix;
mod context;
pub mod transform;
mod test;
mod decode;
pub mod io_wrappers;
pub mod reader;
pub mod writer;
pub use huffman::{HuffmanCode, HuffmanTreeGroup};
pub use state::BrotliState;
#[cfg(feature="ffi-api")]
pub mod ffi;
pub use reader::{DecompressorCustomIo};
#[cfg(feature="std")]
pub use reader::{Decompressor};
pub use writer::{DecompressorWriterCustomIo};
#[cfg(feature="std")]
pub use writer::{DecompressorWriter};
pub use io_wrappers::{CustomRead, CustomWrite};
#[cfg(feature="std")]
pub use io_wrappers::{IntoIoReader, IoReaderWrapper, IntoIoWriter, IoWriterWrapper};
pub use decode::{BrotliDecompressStream, BrotliResult, BrotliDecoderHasMoreOutput, BrotliDecoderIsFinished, BrotliDecoderTakeOutput};
#[cfg(not(any(feature="unsafe", not(feature="std"))))]
pub fn BrotliDecompress<InputType, OutputType>(r: &mut InputType,
w: &mut OutputType)
-> Result<(), io::Error>
where InputType: Read,
OutputType: Write
{
let mut input_buffer: [u8; 4096] = [0; 4096];
let mut output_buffer: [u8; 4096] = [0; 4096];
BrotliDecompressCustomAlloc(r,
w,
&mut input_buffer[..],
&mut output_buffer[..],
StandardAlloc::default(),
StandardAlloc::default(),
StandardAlloc::default(),
)
}
#[cfg(feature="std")]
pub fn BrotliDecompressCustomDict<InputType, OutputType>(r: &mut InputType,
w: &mut OutputType,
input_buffer:&mut [u8],
output_buffer:&mut [u8],
custom_dictionary:std::vec::Vec<u8>)
-> Result<(), io::Error>
where InputType: Read,
OutputType: Write
{
let mut alloc_u8 = brotli_alloc::BrotliAlloc::<u8>::new();
let mut input_buffer_backing;
let mut output_buffer_backing;
{
let mut borrowed_input_buffer = input_buffer;
let mut borrowed_output_buffer = output_buffer;
if borrowed_input_buffer.len() == 0 {
input_buffer_backing = alloc_u8.alloc_cell(4096);
borrowed_input_buffer = input_buffer_backing.slice_mut();
}
if borrowed_output_buffer.len() == 0 {
output_buffer_backing = alloc_u8.alloc_cell(4096);
borrowed_output_buffer = output_buffer_backing.slice_mut();
}
let dict = alloc_u8.take_ownership(custom_dictionary);
BrotliDecompressCustomIoCustomDict(&mut IoReaderWrapper::<InputType>(r),
&mut IoWriterWrapper::<OutputType>(w),
borrowed_input_buffer,
borrowed_output_buffer,
alloc_u8,
brotli_alloc::BrotliAlloc::<u32>::new(),
brotli_alloc::BrotliAlloc::<HuffmanCode>::new(),
dict,
Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF"))
}
}
#[cfg(all(feature="unsafe",feature="std"))]
pub fn BrotliDecompress<InputType, OutputType>(r: &mut InputType,
w: &mut OutputType)
-> Result<(), io::Error>
where InputType: Read,
OutputType: Write
{
let mut input_buffer: [u8; 4096] = [0; 4096];
let mut output_buffer: [u8; 4096] = [0; 4096];
BrotliDecompressCustomAlloc(r,
w,
&mut input_buffer[..],
&mut output_buffer[..],
HeapAlloc::<u8>::new(0),
HeapAlloc::<u32>::new(0),
HeapAlloc::<HuffmanCode>::new(HuffmanCode{ bits:2, value: 1}))
}
#[cfg(feature="std")]
pub fn BrotliDecompressCustomAlloc<InputType,
OutputType,
AllocU8: Allocator<u8>,
AllocU32: Allocator<u32>,
AllocHC: Allocator<HuffmanCode>>
(r: &mut InputType,
w: &mut OutputType,
input_buffer: &mut [u8],
output_buffer: &mut [u8],
alloc_u8: AllocU8,
alloc_u32: AllocU32,
alloc_hc: AllocHC)
-> Result<(), io::Error>
where InputType: Read,
OutputType: Write
{
BrotliDecompressCustomIo(&mut IoReaderWrapper::<InputType>(r),
&mut IoWriterWrapper::<OutputType>(w),
input_buffer,
output_buffer,
alloc_u8,
alloc_u32,
alloc_hc,
Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF"))
}
pub fn BrotliDecompressCustomIo<ErrType,
InputType,
OutputType,
AllocU8: Allocator<u8>,
AllocU32: Allocator<u32>,
AllocHC: Allocator<HuffmanCode>>
(r: &mut InputType,
w: &mut OutputType,
input_buffer: &mut [u8],
output_buffer: &mut [u8],
alloc_u8: AllocU8,
alloc_u32: AllocU32,
alloc_hc: AllocHC,
unexpected_eof_error_constant: ErrType)
-> Result<(), ErrType>
where InputType: CustomRead<ErrType>,
OutputType: CustomWrite<ErrType>
{
BrotliDecompressCustomIoCustomDict(r, w, input_buffer, output_buffer, alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default(), unexpected_eof_error_constant)
}
pub fn BrotliDecompressCustomIoCustomDict<ErrType,
InputType,
OutputType,
AllocU8: Allocator<u8>,
AllocU32: Allocator<u32>,
AllocHC: Allocator<HuffmanCode>>
(r: &mut InputType,
w: &mut OutputType,
input_buffer: &mut [u8],
output_buffer: &mut [u8],
alloc_u8: AllocU8,
alloc_u32: AllocU32,
alloc_hc: AllocHC,
custom_dictionary: AllocU8::AllocatedMemory,
unexpected_eof_error_constant: ErrType)
-> Result<(), ErrType>
where InputType: CustomRead<ErrType>,
OutputType: CustomWrite<ErrType>
{
let mut brotli_state = BrotliState::new_with_custom_dictionary(alloc_u8, alloc_u32, alloc_hc, custom_dictionary);
assert!(input_buffer.len() != 0);
assert!(output_buffer.len() != 0);
let mut available_out: usize = output_buffer.len();
let mut available_in: usize = 0;
let mut input_offset: usize = 0;
let mut output_offset: usize = 0;
let mut result: BrotliResult = BrotliResult::NeedsMoreInput;
loop {
match result {
BrotliResult::NeedsMoreInput => {
input_offset = 0;
match r.read(input_buffer) {
Err(e) => {
return Err(e);
},
Ok(size) => {
if size == 0 {
return Err(unexpected_eof_error_constant);
}
available_in = size;
}
}
}
BrotliResult::NeedsMoreOutput => {
let mut total_written: usize = 0;
while total_written < output_offset {
match w.write(&output_buffer[total_written..output_offset]) {
Err(e) => {
return Result::Err(e);
},
Ok(0) => {
return Result::Err(unexpected_eof_error_constant);
}
Ok(cur_written) => {
total_written += cur_written;
}
}
}
output_offset = 0;
}
BrotliResult::ResultSuccess => break,
BrotliResult::ResultFailure => {
return Err(unexpected_eof_error_constant);
}
}
let mut written: usize = 0;
result = BrotliDecompressStream(&mut available_in,
&mut input_offset,
input_buffer,
&mut available_out,
&mut output_offset,
output_buffer,
&mut written,
&mut brotli_state);
if output_offset != 0 {
let mut total_written: usize = 0;
while total_written < output_offset {
match w.write(&output_buffer[total_written..output_offset]) {
Err(e) => {
return Result::Err(e);
},
Ok(0) => {
return Result::Err(unexpected_eof_error_constant);
}
Ok(cur_written) => {
total_written += cur_written;
}
}
}
output_offset = 0;
available_out = output_buffer.len()
}
}
Ok(())
}
#[cfg(feature="std")]
pub fn copy_from_to<R: io::Read, W: io::Write>(mut r: R, mut w: W) -> io::Result<usize> {
let mut buffer: [u8; 65536] = [0; 65536];
let mut out_size: usize = 0;
loop {
match r.read(&mut buffer[..]) {
Err(e) => {
if let io::ErrorKind::Interrupted = e.kind() {
continue
}
return Err(e);
}
Ok(size) => {
if size == 0 {
break;
} else {
match w.write_all(&buffer[..size]) {
Err(e) => {
if let io::ErrorKind::Interrupted = e.kind() {
continue
}
return Err(e);
}
Ok(_) => out_size += size,
}
}
}
}
}
Ok(out_size)
}
#[repr(C)]
pub struct BrotliDecoderReturnInfo {
pub decoded_size: usize,
pub error_string: [u8;256],
pub error_code: state::BrotliDecoderErrorCode,
pub result: BrotliResult,
}
impl BrotliDecoderReturnInfo {
fn new<AllocU8: Allocator<u8>,
AllocU32: Allocator<u32>,
AllocHC: Allocator<HuffmanCode>>(
state: &BrotliState<AllocU8, AllocU32, AllocHC>,
result: BrotliResult,
output_size: usize,
) -> Self {
let mut ret = BrotliDecoderReturnInfo{
result: result,
decoded_size: output_size,
error_code: decode::BrotliDecoderGetErrorCode(&state),
error_string: if let &Err(msg) = &state.mtf_or_error_string {
msg
} else {
[0u8;256]
},
};
if ret.error_string[0] == 0 {
let error_string = state::BrotliDecoderErrorStr(ret.error_code);
let to_copy = core::cmp::min(error_string.len(), ret.error_string.len() - 1);
for (dst, src) in ret.error_string[..to_copy].iter_mut().zip(error_string[..to_copy].bytes()) {
*dst = src;
}
}
ret
}
}
declare_stack_allocator_struct!(MemPool, 512, stack);
pub fn brotli_decode_prealloc(
input: &[u8],
mut output: &mut[u8],
scratch_u8: &mut [u8],
scratch_u32: &mut [u32],
scratch_hc: &mut [HuffmanCode],
) -> BrotliDecoderReturnInfo {
let stack_u8_allocator = MemPool::<u8>::new_allocator(scratch_u8, bzero);
let stack_u32_allocator = MemPool::<u32>::new_allocator(scratch_u32, bzero);
let stack_hc_allocator = MemPool::<HuffmanCode>::new_allocator(scratch_hc, bzero);
let mut available_out = output.len();
let mut available_in: usize = input.len();
let mut input_offset: usize = 0;
let mut output_offset: usize = 0;
let mut written: usize = 0;
let mut brotli_state =
BrotliState::new(stack_u8_allocator, stack_u32_allocator, stack_hc_allocator);
let result = ::BrotliDecompressStream(&mut available_in,
&mut input_offset,
&input[..],
&mut available_out,
&mut output_offset,
&mut output,
&mut written,
&mut brotli_state);
let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset);
return_info
}
#[cfg(not(feature="std"))]
pub fn brotli_decode(
input: &[u8],
output_and_scratch: &mut[u8],
) -> BrotliDecoderReturnInfo {
let mut stack_u32_buffer = [0u32; 12 * 1024 * 6];
let mut stack_hc_buffer = [HuffmanCode::default(); 128 * (decode::kNumInsertAndCopyCodes as usize + decode::kNumLiteralCodes as usize) + 6 * decode::kNumBlockLengthCodes as usize * huffman::BROTLI_HUFFMAN_MAX_TABLE_SIZE as usize];
let mut guessed_output_size = core::cmp::min(
core::cmp::max(input.len(), output_and_scratch.len() / 3),
output_and_scratch.len());
if input.len() > 2 {
let scratch_len = output_and_scratch.len() - guessed_output_size;
if let Ok(lgwin) = decode::lg_window_size(input[0], input[1]) {
let extra_window_size = 65536 + (decode::kNumLiteralCodes + decode::kNumInsertAndCopyCodes) as usize * 256 + (1usize << lgwin.0) * 5 / 4;
if extra_window_size < scratch_len {
guessed_output_size += (scratch_len - extra_window_size) * 3/4;
}
}
}
let (mut output, mut scratch_space) = output_and_scratch.split_at_mut(guessed_output_size);
let stack_u8_allocator = MemPool::<u8>::new_allocator(&mut scratch_space, bzero);
let stack_u32_allocator = MemPool::<u32>::new_allocator(&mut stack_u32_buffer, bzero);
let stack_hc_allocator = MemPool::<HuffmanCode>::new_allocator(&mut stack_hc_buffer, bzero);
let mut available_out = output.len();
let mut available_in: usize = input.len();
let mut input_offset: usize = 0;
let mut output_offset: usize = 0;
let mut written: usize = 0;
let mut brotli_state =
BrotliState::new(stack_u8_allocator, stack_u32_allocator, stack_hc_allocator);
let result = ::BrotliDecompressStream(&mut available_in,
&mut input_offset,
&input[..],
&mut available_out,
&mut output_offset,
&mut output,
&mut written,
&mut brotli_state);
let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset);
return_info
}
#[cfg(feature="std")]
pub fn brotli_decode(
input: &[u8],
mut output: &mut[u8],
) -> BrotliDecoderReturnInfo {
let mut available_out = output.len();
let mut available_in: usize = input.len();
let mut input_offset: usize = 0;
let mut output_offset: usize = 0;
let mut written: usize = 0;
let mut brotli_state =
BrotliState::new(StandardAlloc::default(), StandardAlloc::default(), StandardAlloc::default());
let result = ::BrotliDecompressStream(&mut available_in,
&mut input_offset,
&input[..],
&mut available_out,
&mut output_offset,
&mut output,
&mut written,
&mut brotli_state);
let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset);
return_info
}