1#![cfg_attr(not(feature = "std"), allow(unused_imports))]
2#[macro_use]
3pub mod vectorization;
4pub mod backward_references;
5pub mod bit_cost;
6pub mod block_split;
7pub mod brotli_bit_stream;
8pub mod cluster;
9pub mod combined_alloc;
10pub mod command;
11pub mod constants;
12pub mod dictionary_hash;
13pub mod entropy_encode;
14pub mod fast_log;
15pub mod histogram;
16pub mod input_pair;
17pub mod literal_cost;
18pub mod static_dict;
19pub mod static_dict_lut;
20pub mod utf8_util;
21pub mod util;
22pub use self::backward_references::hash_to_binary_tree;
23pub use self::backward_references::hq as backward_references_hq;
24pub mod block_splitter;
25pub mod compress_fragment;
26pub mod compress_fragment_two_pass;
27pub mod context_map_entropy;
28pub mod encode;
29pub mod find_stride;
30pub mod interface;
31pub mod ir_interpret;
32pub mod metablock;
33pub mod pdf;
34pub mod prior_eval;
35pub mod reader;
36pub mod stride_eval;
37pub mod writer;
38pub use self::combined_alloc::{BrotliAlloc, CombiningAllocator};
39mod compat;
40pub mod fixed_queue;
41pub mod multithreading;
42pub mod singlethreading;
43pub mod threading;
44pub mod worker_pool;
45#[cfg(feature = "simd")]
46pub type s16 = core::simd::i16x16;
47#[cfg(feature = "simd")]
48pub type v8 = core::simd::f32x8;
49#[cfg(feature = "simd")]
50pub type s8 = core::simd::i32x8;
51#[cfg(not(feature = "simd"))]
52pub type s16 = compat::Compat16x16;
53#[cfg(not(feature = "simd"))]
54pub type v8 = compat::CompatF8;
55#[cfg(not(feature = "simd"))]
56pub type s8 = compat::Compat32x8;
57
58mod parameters;
59mod test;
60mod weights;
61pub use self::backward_references::{BrotliEncoderParams, UnionHasher};
62use self::encode::{BrotliEncoderDestroyInstance, BrotliEncoderOperation};
63pub use self::encode::{
64 BrotliEncoderInitParams, BrotliEncoderMaxCompressedSize, BrotliEncoderMaxCompressedSizeMulti,
65};
66pub use self::hash_to_binary_tree::ZopfliNode;
67pub use self::interface::StaticCommand;
68pub use self::pdf::PDF;
69pub use self::util::floatX;
70pub use self::vectorization::{v256, v256i, Mem256f};
71use brotli_decompressor::{CustomRead, CustomWrite};
72pub use interface::{InputPair, InputReference, InputReferenceMut};
73
74pub use alloc::{AllocatedStackMemory, Allocator, SliceWrapper, SliceWrapperMut, StackAllocator};
75#[cfg(feature = "std")]
76pub use alloc_stdlib::StandardAlloc;
77#[cfg(feature = "std")]
78use std::io;
79#[cfg(feature = "std")]
80use std::io::{Error, ErrorKind, Read, Write};
81
82#[cfg(feature = "std")]
83pub use brotli_decompressor::{IntoIoReader, IoReaderWrapper, IoWriterWrapper};
84use enc::encode::BrotliEncoderStateStruct;
85
86#[cfg(not(feature = "std"))]
87pub use self::singlethreading::{compress_worker_pool, new_work_pool, WorkerPool};
88pub use self::threading::{
89 BatchSpawnableLite, BrotliEncoderThreadError, CompressionThreadResult, Owned, SendAlloc,
90};
91#[cfg(feature = "std")]
92pub use self::worker_pool::{compress_worker_pool, new_work_pool, WorkerPool};
93#[cfg(feature = "std")]
94pub fn compress_multi<
95 Alloc: BrotliAlloc + Send + 'static,
96 SliceW: SliceWrapper<u8> + Send + 'static + Sync,
97>(
98 params: &BrotliEncoderParams,
99 owned_input: &mut Owned<SliceW>,
100 output: &mut [u8],
101 alloc_per_thread: &mut [SendAlloc<
102 CompressionThreadResult<Alloc>,
103 backward_references::UnionHasher<Alloc>,
104 Alloc,
105 <WorkerPool<
106 CompressionThreadResult<Alloc>,
107 backward_references::UnionHasher<Alloc>,
108 Alloc,
109 (SliceW, BrotliEncoderParams),
110 > as BatchSpawnableLite<
111 CompressionThreadResult<Alloc>,
112 backward_references::UnionHasher<Alloc>,
113 Alloc,
114 (SliceW, BrotliEncoderParams),
115 >>::JoinHandle,
116 >],
117) -> Result<usize, BrotliEncoderThreadError>
118where
119 <Alloc as Allocator<u8>>::AllocatedMemory: Send,
120 <Alloc as Allocator<u16>>::AllocatedMemory: Send + Sync,
121 <Alloc as Allocator<u32>>::AllocatedMemory: Send + Sync,
122{
123 let mut work_pool = self::worker_pool::new_work_pool(alloc_per_thread.len() - 1);
124 compress_worker_pool(
125 params,
126 owned_input,
127 output,
128 alloc_per_thread,
129 &mut work_pool,
130 )
131}
132
133#[cfg(feature = "std")]
134pub use self::multithreading::compress_multi as compress_multi_no_threadpool;
135#[cfg(not(feature = "std"))]
136pub use self::singlethreading::compress_multi;
137#[cfg(not(feature = "std"))]
138pub use self::singlethreading::compress_multi as compress_multi_no_threadpool;
139
140#[cfg(feature = "std")]
141pub fn BrotliCompress<InputType, OutputType>(
142 r: &mut InputType,
143 w: &mut OutputType,
144 params: &BrotliEncoderParams,
145) -> Result<usize, io::Error>
146where
147 InputType: Read,
148 OutputType: Write,
149{
150 let mut input_buffer: [u8; 4096] = [0; 4096];
151 let mut output_buffer: [u8; 4096] = [0; 4096];
152 BrotliCompressCustomAlloc(
153 r,
154 w,
155 &mut input_buffer[..],
156 &mut output_buffer[..],
157 params,
158 StandardAlloc::default(),
159 )
160}
161
162#[cfg(feature = "std")]
163pub fn BrotliCompressCustomAlloc<InputType, OutputType, Alloc: BrotliAlloc>(
164 r: &mut InputType,
165 w: &mut OutputType,
166 input_buffer: &mut [u8],
167 output_buffer: &mut [u8],
168 params: &BrotliEncoderParams,
169 alloc: Alloc,
170) -> Result<usize, io::Error>
171where
172 InputType: Read,
173 OutputType: Write,
174{
175 let mut nop_callback = |_data: &mut interface::PredictionModeContextMap<InputReferenceMut>,
176 _cmds: &mut [interface::StaticCommand],
177 _mb: interface::InputPair,
178 _m: &mut Alloc| ();
179 BrotliCompressCustomIo(
180 &mut IoReaderWrapper::<InputType>(r),
181 &mut IoWriterWrapper::<OutputType>(w),
182 input_buffer,
183 output_buffer,
184 params,
185 alloc,
186 &mut nop_callback,
187 Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF"),
188 )
189}
190
191pub fn BrotliCompressCustomIo<
192 ErrType,
193 InputType,
194 OutputType,
195 Alloc: BrotliAlloc,
196 MetablockCallback: FnMut(
197 &mut interface::PredictionModeContextMap<InputReferenceMut>,
198 &mut [interface::StaticCommand],
199 interface::InputPair,
200 &mut Alloc,
201 ),
202>(
203 r: &mut InputType,
204 w: &mut OutputType,
205 input_buffer: &mut [u8],
206 output_buffer: &mut [u8],
207 params: &BrotliEncoderParams,
208 alloc: Alloc,
209 metablock_callback: &mut MetablockCallback,
210 unexpected_eof_error_constant: ErrType,
211) -> Result<usize, ErrType>
212where
213 InputType: CustomRead<ErrType>,
214 OutputType: CustomWrite<ErrType>,
215{
216 BrotliCompressCustomIoCustomDict(
217 r,
218 w,
219 input_buffer,
220 output_buffer,
221 params,
222 alloc,
223 metablock_callback,
224 &[],
225 unexpected_eof_error_constant,
226 )
227}
228pub fn BrotliCompressCustomIoCustomDict<
229 ErrType,
230 InputType,
231 OutputType,
232 Alloc: BrotliAlloc,
233 MetablockCallback: FnMut(
234 &mut interface::PredictionModeContextMap<InputReferenceMut>,
235 &mut [interface::StaticCommand],
236 interface::InputPair,
237 &mut Alloc,
238 ),
239>(
240 r: &mut InputType,
241 w: &mut OutputType,
242 input_buffer: &mut [u8],
243 output_buffer: &mut [u8],
244 params: &BrotliEncoderParams,
245 alloc: Alloc,
246 metablock_callback: &mut MetablockCallback,
247 dict: &[u8],
248 unexpected_eof_error_constant: ErrType,
249) -> Result<usize, ErrType>
250where
251 InputType: CustomRead<ErrType>,
252 OutputType: CustomWrite<ErrType>,
253{
254 assert!(!input_buffer.is_empty());
255 assert!(!output_buffer.is_empty());
256 let mut s_orig = BrotliEncoderStateStruct::new(alloc);
257 s_orig.params = params.clone();
258 if !dict.is_empty() {
259 s_orig.set_custom_dictionary(dict.len(), dict);
260 }
261 let mut next_in_offset: usize = 0;
262 let mut next_out_offset: usize = 0;
263 let mut total_out = Some(0);
264 let mut read_err: Result<(), ErrType> = Ok(());
265 {
266 let s = &mut s_orig;
267
268 let mut available_in: usize = 0;
273 let mut available_out: usize = output_buffer.len();
274 let mut eof = false;
275 loop {
276 if available_in == 0 && !eof {
277 next_in_offset = 0;
278 match r.read(input_buffer) {
279 Err(e) => {
280 read_err = Err(e);
281 available_in = 0;
282 eof = true;
283 }
284 Ok(size) => {
285 if size == 0 {
286 eof = true;
287 }
288 available_in = size;
289 }
290 }
291 }
292 let op: BrotliEncoderOperation;
293 if available_in == 0 {
294 op = BrotliEncoderOperation::BROTLI_OPERATION_FINISH;
295 } else {
296 op = BrotliEncoderOperation::BROTLI_OPERATION_PROCESS;
297 }
298 let result = s.compress_stream(
299 op,
300 &mut available_in,
301 input_buffer,
302 &mut next_in_offset,
303 &mut available_out,
304 output_buffer,
305 &mut next_out_offset,
306 &mut total_out,
307 metablock_callback,
308 );
309 let fin = s.is_finished();
310 if available_out == 0 || fin {
311 let lim = output_buffer.len() - available_out;
312 assert_eq!(next_out_offset, lim);
313 next_out_offset = 0;
314 while next_out_offset < lim {
315 match w.write(&mut output_buffer[next_out_offset..lim]) {
316 Err(e) => {
317 BrotliEncoderDestroyInstance(s);
318 read_err?;
319 return Err(e);
320 }
321 Ok(size) => {
322 next_out_offset += size;
323 }
324 }
325 }
326 available_out = output_buffer.len();
327 next_out_offset = 0;
328 }
329 if !result {
330 if read_err.is_ok() {
331 read_err = Err(unexpected_eof_error_constant);
332 }
333 break;
334 }
335 if fin {
336 break;
337 }
338 }
339 BrotliEncoderDestroyInstance(s);
340 }
341 read_err?;
342 Ok(total_out.unwrap())
343}