Coverage Report

Created: 2026-01-10 06:48

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}