/rust/registry/src/index.crates.io-1949cf8c6b5b557f/brotli-decompressor-5.0.0/src/lib.rs
Line | Count | Source |
1 | | #![no_std] |
2 | | #![allow(non_snake_case)] |
3 | | #![allow(unused_parens)] |
4 | | #![allow(unused_imports)] |
5 | | #![allow(non_camel_case_types)] |
6 | | #![allow(non_snake_case)] |
7 | | #![allow(non_upper_case_globals)] |
8 | | #![cfg_attr(feature="no-stdlib-ffi-binding",cfg_attr(not(feature="std"), feature(lang_items)))] |
9 | | #![cfg_attr(feature="no-stdlib-ffi-binding",cfg_attr(not(feature="std"), feature(panic_handler)))] |
10 | | |
11 | | |
12 | | #[macro_use] |
13 | | // <-- for debugging, remove xprintln from bit_reader and replace with println |
14 | | #[cfg(feature="std")] |
15 | | extern crate std; |
16 | | #[cfg(feature="std")] |
17 | | use std::io::{self, Error, ErrorKind, Read, Write}; |
18 | | #[cfg(feature="std")] |
19 | | extern crate alloc_stdlib; |
20 | | #[macro_use] |
21 | | extern crate alloc_no_stdlib as alloc; |
22 | | pub use alloc::{AllocatedStackMemory, Allocator, SliceWrapper, SliceWrapperMut, StackAllocator, bzero}; |
23 | | use core::ops; |
24 | | |
25 | | #[cfg(feature="std")] |
26 | | pub use alloc_stdlib::StandardAlloc; |
27 | | #[cfg(all(feature="unsafe",feature="std"))] |
28 | | pub use alloc_stdlib::HeapAlloc; |
29 | | #[macro_use] |
30 | | mod memory; |
31 | | pub mod dictionary; |
32 | | mod brotli_alloc; |
33 | | #[macro_use] |
34 | | mod bit_reader; |
35 | | mod huffman; |
36 | | mod state; |
37 | | mod prefix; |
38 | | mod context; |
39 | | pub mod transform; |
40 | | mod test; |
41 | | mod decode; |
42 | | pub mod io_wrappers; |
43 | | pub mod reader; |
44 | | pub mod writer; |
45 | | pub use huffman::{HuffmanCode, HuffmanTreeGroup}; |
46 | | pub use state::BrotliState; |
47 | | #[cfg(feature="ffi-api")] |
48 | | pub mod ffi; |
49 | | pub use reader::{DecompressorCustomIo}; |
50 | | |
51 | | #[cfg(feature="std")] |
52 | | pub use reader::{Decompressor}; |
53 | | |
54 | | pub use writer::{DecompressorWriterCustomIo}; |
55 | | #[cfg(feature="std")] |
56 | | pub use writer::{DecompressorWriter}; |
57 | | |
58 | | // use io_wrappers::write_all; |
59 | | pub use io_wrappers::{CustomRead, CustomWrite}; |
60 | | #[cfg(feature="std")] |
61 | | pub use io_wrappers::{IntoIoReader, IoReaderWrapper, IntoIoWriter, IoWriterWrapper}; |
62 | | |
63 | | // interface |
64 | | // pub fn BrotliDecompressStream(mut available_in: &mut usize, |
65 | | // input_offset: &mut usize, |
66 | | // input: &[u8], |
67 | | // mut available_out: &mut usize, |
68 | | // mut output_offset: &mut usize, |
69 | | // mut output: &mut [u8], |
70 | | // mut total_out: &mut usize, |
71 | | // mut s: &mut BrotliState<AllocU8, AllocU32, AllocHC>); |
72 | | |
73 | | pub use decode::{BrotliDecompressStream, BrotliResult, BrotliDecoderHasMoreOutput, BrotliDecoderIsFinished, BrotliDecoderTakeOutput}; |
74 | | |
75 | | |
76 | | |
77 | | |
78 | | #[cfg(not(any(feature="unsafe", not(feature="std"))))] |
79 | 0 | pub fn BrotliDecompress<InputType, OutputType>(r: &mut InputType, |
80 | 0 | w: &mut OutputType) |
81 | 0 | -> Result<(), io::Error> |
82 | 0 | where InputType: Read, |
83 | 0 | OutputType: Write |
84 | | { |
85 | 0 | let mut input_buffer: [u8; 4096] = [0; 4096]; |
86 | 0 | let mut output_buffer: [u8; 4096] = [0; 4096]; |
87 | 0 | BrotliDecompressCustomAlloc(r, |
88 | 0 | w, |
89 | 0 | &mut input_buffer[..], |
90 | 0 | &mut output_buffer[..], |
91 | 0 | StandardAlloc::default(), |
92 | 0 | StandardAlloc::default(), |
93 | 0 | StandardAlloc::default(), |
94 | | ) |
95 | 0 | } |
96 | | |
97 | | #[cfg(feature="std")] |
98 | 0 | pub fn BrotliDecompressCustomDict<InputType, OutputType>(r: &mut InputType, |
99 | 0 | w: &mut OutputType, |
100 | 0 | input_buffer:&mut [u8], |
101 | 0 | output_buffer:&mut [u8], |
102 | 0 | custom_dictionary:std::vec::Vec<u8>) |
103 | 0 | -> Result<(), io::Error> |
104 | 0 | where InputType: Read, |
105 | 0 | OutputType: Write |
106 | | { |
107 | 0 | let mut alloc_u8 = brotli_alloc::BrotliAlloc::<u8>::new(); |
108 | | let mut input_buffer_backing; |
109 | | let mut output_buffer_backing; |
110 | | { |
111 | 0 | let mut borrowed_input_buffer = input_buffer; |
112 | 0 | let mut borrowed_output_buffer = output_buffer; |
113 | 0 | if borrowed_input_buffer.len() == 0 { |
114 | 0 | input_buffer_backing = alloc_u8.alloc_cell(4096); |
115 | 0 | borrowed_input_buffer = input_buffer_backing.slice_mut(); |
116 | 0 | } |
117 | 0 | if borrowed_output_buffer.len() == 0 { |
118 | 0 | output_buffer_backing = alloc_u8.alloc_cell(4096); |
119 | 0 | borrowed_output_buffer = output_buffer_backing.slice_mut(); |
120 | 0 | } |
121 | 0 | let dict = alloc_u8.take_ownership(custom_dictionary); |
122 | 0 | BrotliDecompressCustomIoCustomDict(&mut IoReaderWrapper::<InputType>(r), |
123 | 0 | &mut IoWriterWrapper::<OutputType>(w), |
124 | 0 | borrowed_input_buffer, |
125 | 0 | borrowed_output_buffer, |
126 | 0 | alloc_u8, |
127 | 0 | brotli_alloc::BrotliAlloc::<u32>::new(), |
128 | 0 | brotli_alloc::BrotliAlloc::<HuffmanCode>::new(), |
129 | 0 | dict, |
130 | 0 | Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF")) |
131 | | } |
132 | 0 | } |
133 | | |
134 | | #[cfg(all(feature="unsafe",feature="std"))] |
135 | | pub fn BrotliDecompress<InputType, OutputType>(r: &mut InputType, |
136 | | w: &mut OutputType) |
137 | | -> Result<(), io::Error> |
138 | | where InputType: Read, |
139 | | OutputType: Write |
140 | | { |
141 | | let mut input_buffer: [u8; 4096] = [0; 4096]; |
142 | | let mut output_buffer: [u8; 4096] = [0; 4096]; |
143 | | BrotliDecompressCustomAlloc(r, |
144 | | w, |
145 | | &mut input_buffer[..], |
146 | | &mut output_buffer[..], |
147 | | HeapAlloc::<u8>::new(0), |
148 | | HeapAlloc::<u32>::new(0), |
149 | | HeapAlloc::<HuffmanCode>::new(HuffmanCode{ bits:2, value: 1})) |
150 | | } |
151 | | |
152 | | |
153 | | #[cfg(feature="std")] |
154 | 0 | pub fn BrotliDecompressCustomAlloc<InputType, |
155 | 0 | OutputType, |
156 | 0 | AllocU8: Allocator<u8>, |
157 | 0 | AllocU32: Allocator<u32>, |
158 | 0 | AllocHC: Allocator<HuffmanCode>> |
159 | 0 | (r: &mut InputType, |
160 | 0 | w: &mut OutputType, |
161 | 0 | input_buffer: &mut [u8], |
162 | 0 | output_buffer: &mut [u8], |
163 | 0 | alloc_u8: AllocU8, |
164 | 0 | alloc_u32: AllocU32, |
165 | 0 | alloc_hc: AllocHC) |
166 | 0 | -> Result<(), io::Error> |
167 | 0 | where InputType: Read, |
168 | 0 | OutputType: Write |
169 | | { |
170 | 0 | BrotliDecompressCustomIo(&mut IoReaderWrapper::<InputType>(r), |
171 | 0 | &mut IoWriterWrapper::<OutputType>(w), |
172 | 0 | input_buffer, |
173 | 0 | output_buffer, |
174 | 0 | alloc_u8, |
175 | 0 | alloc_u32, |
176 | 0 | alloc_hc, |
177 | 0 | Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF")) |
178 | 0 | } |
179 | 0 | pub fn BrotliDecompressCustomIo<ErrType, |
180 | 0 | InputType, |
181 | 0 | OutputType, |
182 | 0 | AllocU8: Allocator<u8>, |
183 | 0 | AllocU32: Allocator<u32>, |
184 | 0 | AllocHC: Allocator<HuffmanCode>> |
185 | 0 | (r: &mut InputType, |
186 | 0 | w: &mut OutputType, |
187 | 0 | input_buffer: &mut [u8], |
188 | 0 | output_buffer: &mut [u8], |
189 | 0 | alloc_u8: AllocU8, |
190 | 0 | alloc_u32: AllocU32, |
191 | 0 | alloc_hc: AllocHC, |
192 | 0 | unexpected_eof_error_constant: ErrType) |
193 | 0 | -> Result<(), ErrType> |
194 | 0 | where InputType: CustomRead<ErrType>, |
195 | 0 | OutputType: CustomWrite<ErrType> |
196 | | { |
197 | 0 | BrotliDecompressCustomIoCustomDict(r, w, input_buffer, output_buffer, alloc_u8, alloc_u32, alloc_hc, AllocU8::AllocatedMemory::default(), unexpected_eof_error_constant) |
198 | 0 | } |
199 | 0 | pub fn BrotliDecompressCustomIoCustomDict<ErrType, |
200 | 0 | InputType, |
201 | 0 | OutputType, |
202 | 0 | AllocU8: Allocator<u8>, |
203 | 0 | AllocU32: Allocator<u32>, |
204 | 0 | AllocHC: Allocator<HuffmanCode>> |
205 | 0 | (r: &mut InputType, |
206 | 0 | w: &mut OutputType, |
207 | 0 | input_buffer: &mut [u8], |
208 | 0 | output_buffer: &mut [u8], |
209 | 0 | alloc_u8: AllocU8, |
210 | 0 | alloc_u32: AllocU32, |
211 | 0 | alloc_hc: AllocHC, |
212 | 0 | custom_dictionary: AllocU8::AllocatedMemory, |
213 | 0 | unexpected_eof_error_constant: ErrType) |
214 | 0 | -> Result<(), ErrType> |
215 | 0 | where InputType: CustomRead<ErrType>, |
216 | 0 | OutputType: CustomWrite<ErrType> |
217 | | { |
218 | 0 | let mut brotli_state = BrotliState::new_with_custom_dictionary(alloc_u8, alloc_u32, alloc_hc, custom_dictionary); |
219 | 0 | assert!(input_buffer.len() != 0); |
220 | 0 | assert!(output_buffer.len() != 0); |
221 | 0 | let mut available_out: usize = output_buffer.len(); |
222 | | |
223 | 0 | let mut available_in: usize = 0; |
224 | 0 | let mut input_offset: usize = 0; |
225 | 0 | let mut output_offset: usize = 0; |
226 | 0 | let mut result: BrotliResult = BrotliResult::NeedsMoreInput; |
227 | | loop { |
228 | 0 | match result { |
229 | | BrotliResult::NeedsMoreInput => { |
230 | 0 | input_offset = 0; |
231 | 0 | match r.read(input_buffer) { |
232 | 0 | Err(e) => { |
233 | 0 | return Err(e); |
234 | | }, |
235 | 0 | Ok(size) => { |
236 | 0 | if size == 0 { |
237 | 0 | return Err(unexpected_eof_error_constant); |
238 | 0 | } |
239 | 0 | available_in = size; |
240 | | } |
241 | | } |
242 | | } |
243 | | BrotliResult::NeedsMoreOutput => { |
244 | 0 | let mut total_written: usize = 0; |
245 | 0 | while total_written < output_offset { |
246 | | // this would be a call to write_all |
247 | 0 | match w.write(&output_buffer[total_written..output_offset]) { |
248 | 0 | Err(e) => { |
249 | 0 | return Result::Err(e); |
250 | | }, |
251 | | Ok(0) => { |
252 | 0 | return Result::Err(unexpected_eof_error_constant); |
253 | | } |
254 | 0 | Ok(cur_written) => { |
255 | 0 | total_written += cur_written; |
256 | 0 | } |
257 | | } |
258 | | } |
259 | | |
260 | 0 | output_offset = 0; |
261 | | } |
262 | 0 | BrotliResult::ResultSuccess => break, |
263 | | BrotliResult::ResultFailure => { |
264 | 0 | return Err(unexpected_eof_error_constant); |
265 | | } |
266 | | } |
267 | 0 | let mut written: usize = 0; |
268 | 0 | result = BrotliDecompressStream(&mut available_in, |
269 | 0 | &mut input_offset, |
270 | 0 | input_buffer, |
271 | 0 | &mut available_out, |
272 | 0 | &mut output_offset, |
273 | 0 | output_buffer, |
274 | 0 | &mut written, |
275 | 0 | &mut brotli_state); |
276 | | |
277 | 0 | if output_offset != 0 { |
278 | 0 | let mut total_written: usize = 0; |
279 | 0 | while total_written < output_offset { |
280 | 0 | match w.write(&output_buffer[total_written..output_offset]) { |
281 | 0 | Err(e) => { |
282 | 0 | return Result::Err(e); |
283 | | }, |
284 | | // CustomResult::Transient(e) => continue, |
285 | | Ok(0) => { |
286 | 0 | return Result::Err(unexpected_eof_error_constant); |
287 | | } |
288 | 0 | Ok(cur_written) => { |
289 | 0 | total_written += cur_written; |
290 | 0 | } |
291 | | } |
292 | | } |
293 | 0 | output_offset = 0; |
294 | 0 | available_out = output_buffer.len() |
295 | 0 | } |
296 | | } |
297 | 0 | Ok(()) |
298 | 0 | } |
299 | | |
300 | | |
301 | | #[cfg(feature="std")] |
302 | 0 | pub fn copy_from_to<R: io::Read, W: io::Write>(mut r: R, mut w: W) -> io::Result<usize> { |
303 | 0 | let mut buffer: [u8; 65536] = [0; 65536]; |
304 | 0 | let mut out_size: usize = 0; |
305 | | loop { |
306 | 0 | match r.read(&mut buffer[..]) { |
307 | 0 | Err(e) => { |
308 | 0 | if let io::ErrorKind::Interrupted = e.kind() { |
309 | 0 | continue |
310 | 0 | } |
311 | 0 | return Err(e); |
312 | | } |
313 | 0 | Ok(size) => { |
314 | 0 | if size == 0 { |
315 | 0 | break; |
316 | | } else { |
317 | 0 | match w.write_all(&buffer[..size]) { |
318 | 0 | Err(e) => { |
319 | 0 | if let io::ErrorKind::Interrupted = e.kind() { |
320 | 0 | continue |
321 | 0 | } |
322 | 0 | return Err(e); |
323 | | } |
324 | 0 | Ok(_) => out_size += size, |
325 | | } |
326 | | } |
327 | | } |
328 | | } |
329 | | } |
330 | 0 | Ok(out_size) |
331 | 0 | } |
332 | | |
333 | | #[repr(C)] |
334 | | pub struct BrotliDecoderReturnInfo { |
335 | | pub decoded_size: usize, |
336 | | pub error_string: [u8;256], |
337 | | pub error_code: state::BrotliDecoderErrorCode, |
338 | | pub result: BrotliResult, |
339 | | } |
340 | | impl BrotliDecoderReturnInfo { |
341 | 0 | fn new<AllocU8: Allocator<u8>, |
342 | 0 | AllocU32: Allocator<u32>, |
343 | 0 | AllocHC: Allocator<HuffmanCode>>( |
344 | 0 | state: &BrotliState<AllocU8, AllocU32, AllocHC>, |
345 | 0 | result: BrotliResult, |
346 | 0 | output_size: usize, |
347 | 0 | ) -> Self { |
348 | 0 | let mut ret = BrotliDecoderReturnInfo{ |
349 | 0 | result: result, |
350 | 0 | decoded_size: output_size, |
351 | 0 | error_code: decode::BrotliDecoderGetErrorCode(&state), |
352 | 0 | error_string: if let &Err(msg) = &state.mtf_or_error_string { |
353 | 0 | msg |
354 | | } else { |
355 | 0 | [0u8;256] |
356 | | }, |
357 | | }; |
358 | 0 | if ret.error_string[0] == 0 { |
359 | 0 | let error_string = state::BrotliDecoderErrorStr(ret.error_code); |
360 | 0 | let to_copy = core::cmp::min(error_string.len(), ret.error_string.len() - 1); |
361 | 0 | for (dst, src) in ret.error_string[..to_copy].iter_mut().zip(error_string[..to_copy].bytes()) { |
362 | 0 | *dst = src; |
363 | 0 | } |
364 | 0 | } |
365 | 0 | ret |
366 | 0 | } Unexecuted instantiation: <brotli_decompressor::BrotliDecoderReturnInfo>::new::<alloc_no_stdlib::stack_allocator::StackAllocator<u8, brotli_decompressor::MemPool<u8>>, alloc_no_stdlib::stack_allocator::StackAllocator<u32, brotli_decompressor::MemPool<u32>>, alloc_no_stdlib::stack_allocator::StackAllocator<brotli_decompressor::huffman::HuffmanCode, brotli_decompressor::MemPool<brotli_decompressor::huffman::HuffmanCode>>> Unexecuted instantiation: <brotli_decompressor::BrotliDecoderReturnInfo>::new::<alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc, alloc_stdlib::std_alloc::StandardAlloc> |
367 | | } |
368 | | |
369 | | declare_stack_allocator_struct!(MemPool, 512, stack); |
370 | | |
371 | 0 | pub fn brotli_decode_prealloc( |
372 | 0 | input: &[u8], |
373 | 0 | mut output: &mut[u8], |
374 | 0 | scratch_u8: &mut [u8], |
375 | 0 | scratch_u32: &mut [u32], |
376 | 0 | scratch_hc: &mut [HuffmanCode], |
377 | 0 | ) -> BrotliDecoderReturnInfo { |
378 | 0 | let stack_u8_allocator = MemPool::<u8>::new_allocator(scratch_u8, bzero); |
379 | 0 | let stack_u32_allocator = MemPool::<u32>::new_allocator(scratch_u32, bzero); |
380 | 0 | let stack_hc_allocator = MemPool::<HuffmanCode>::new_allocator(scratch_hc, bzero); |
381 | 0 | let mut available_out = output.len(); |
382 | 0 | let mut available_in: usize = input.len(); |
383 | 0 | let mut input_offset: usize = 0; |
384 | 0 | let mut output_offset: usize = 0; |
385 | 0 | let mut written: usize = 0; |
386 | 0 | let mut brotli_state = |
387 | 0 | BrotliState::new(stack_u8_allocator, stack_u32_allocator, stack_hc_allocator); |
388 | 0 | let result = ::BrotliDecompressStream(&mut available_in, |
389 | 0 | &mut input_offset, |
390 | 0 | &input[..], |
391 | 0 | &mut available_out, |
392 | 0 | &mut output_offset, |
393 | 0 | &mut output, |
394 | 0 | &mut written, |
395 | 0 | &mut brotli_state); |
396 | 0 | let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset); |
397 | 0 | return_info |
398 | 0 | } |
399 | | |
400 | | #[cfg(not(feature="std"))] |
401 | | pub fn brotli_decode( |
402 | | input: &[u8], |
403 | | output_and_scratch: &mut[u8], |
404 | | ) -> BrotliDecoderReturnInfo { |
405 | | let mut stack_u32_buffer = [0u32; 12 * 1024 * 6]; |
406 | | 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]; |
407 | | let mut guessed_output_size = core::cmp::min( |
408 | | core::cmp::max(input.len(), // shouldn't shrink too much |
409 | | output_and_scratch.len() / 3), |
410 | | output_and_scratch.len()); |
411 | | if input.len() > 2 { |
412 | | let scratch_len = output_and_scratch.len() - guessed_output_size; |
413 | | if let Ok(lgwin) = decode::lg_window_size(input[0], input[1]) { |
414 | | let extra_window_size = 65536 + (decode::kNumLiteralCodes + decode::kNumInsertAndCopyCodes) as usize * 256 + (1usize << lgwin.0) * 5 / 4; |
415 | | if extra_window_size < scratch_len { |
416 | | guessed_output_size += (scratch_len - extra_window_size) * 3/4; |
417 | | } |
418 | | } |
419 | | } |
420 | | let (mut output, mut scratch_space) = output_and_scratch.split_at_mut(guessed_output_size); |
421 | | let stack_u8_allocator = MemPool::<u8>::new_allocator(&mut scratch_space, bzero); |
422 | | let stack_u32_allocator = MemPool::<u32>::new_allocator(&mut stack_u32_buffer, bzero); |
423 | | let stack_hc_allocator = MemPool::<HuffmanCode>::new_allocator(&mut stack_hc_buffer, bzero); |
424 | | let mut available_out = output.len(); |
425 | | let mut available_in: usize = input.len(); |
426 | | let mut input_offset: usize = 0; |
427 | | let mut output_offset: usize = 0; |
428 | | let mut written: usize = 0; |
429 | | let mut brotli_state = |
430 | | BrotliState::new(stack_u8_allocator, stack_u32_allocator, stack_hc_allocator); |
431 | | let result = ::BrotliDecompressStream(&mut available_in, |
432 | | &mut input_offset, |
433 | | &input[..], |
434 | | &mut available_out, |
435 | | &mut output_offset, |
436 | | &mut output, |
437 | | &mut written, |
438 | | &mut brotli_state); |
439 | | let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset); |
440 | | return_info |
441 | | } |
442 | | |
443 | | #[cfg(feature="std")] |
444 | 0 | pub fn brotli_decode( |
445 | 0 | input: &[u8], |
446 | 0 | mut output: &mut[u8], |
447 | 0 | ) -> BrotliDecoderReturnInfo { |
448 | 0 | let mut available_out = output.len(); |
449 | 0 | let mut available_in: usize = input.len(); |
450 | 0 | let mut input_offset: usize = 0; |
451 | 0 | let mut output_offset: usize = 0; |
452 | 0 | let mut written: usize = 0; |
453 | 0 | let mut brotli_state = |
454 | 0 | BrotliState::new(StandardAlloc::default(), StandardAlloc::default(), StandardAlloc::default()); |
455 | 0 | let result = ::BrotliDecompressStream(&mut available_in, |
456 | 0 | &mut input_offset, |
457 | 0 | &input[..], |
458 | 0 | &mut available_out, |
459 | 0 | &mut output_offset, |
460 | 0 | &mut output, |
461 | 0 | &mut written, |
462 | 0 | &mut brotli_state); |
463 | 0 | let return_info = BrotliDecoderReturnInfo::new(&brotli_state, result.into(), output_offset); |
464 | 0 | return_info |
465 | 0 | } |