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