Skip to main content

compression/
compression_decode.rs

1use crate::{ffi, Algorithm, CompressionError, Decoder, Result};
2
3fn decode_len(dst: &mut [u8], src: &[u8], algorithm: Algorithm) -> usize {
4    unsafe {
5        ffi::compression_decode::compression_rs_compression_decode_buffer(
6            dst.as_mut_ptr(),
7            dst.len(),
8            src.as_ptr(),
9            src.len(),
10            algorithm.as_raw(),
11        )
12    }
13}
14
15pub fn compression_decode_scratch_buffer_size(algorithm: Algorithm) -> usize {
16    unsafe {
17        ffi::compression_decode::compression_rs_compression_decode_scratch_buffer_size(
18            algorithm.as_raw(),
19        )
20    }
21}
22
23pub fn compression_decode_buffer(
24    dst: &mut [u8],
25    src: &[u8],
26    algorithm: Algorithm,
27) -> Result<usize> {
28    let written = decode_len(dst, src, algorithm);
29    if src.is_empty() || written > 0 {
30        Ok(written)
31    } else {
32        Err(CompressionError::BufferOperationFailed {
33            operation: "compression_decode_buffer",
34            algorithm,
35            input_len: src.len(),
36            output_capacity: dst.len(),
37        })
38    }
39}
40
41pub fn decompress(input: &[u8], algorithm: Algorithm) -> Result<Vec<u8>> {
42    if input.is_empty() {
43        return Ok(Vec::new());
44    }
45
46    if algorithm.supports_streams() {
47        let mut decoder = Decoder::new(algorithm)?;
48        let mut output = decoder.process(input)?;
49        output.extend(decoder.finish()?);
50        return Ok(output);
51    }
52
53    let mut capacity = 4 * 1024;
54    let max_capacity = 64 * 1024 * 1024;
55    loop {
56        let mut output = vec![0_u8; capacity];
57        let written = decode_len(&mut output, input, algorithm);
58        if written == 0 {
59            return Err(CompressionError::BufferOperationFailed {
60                operation: "compression_decode_buffer",
61                algorithm,
62                input_len: input.len(),
63                output_capacity: capacity,
64            });
65        }
66        if written < capacity {
67            output.truncate(written);
68            return Ok(output);
69        }
70        if capacity >= max_capacity {
71            return Err(CompressionError::BufferOperationFailed {
72                operation: "compression_decode_buffer",
73                algorithm,
74                input_len: input.len(),
75                output_capacity: capacity,
76            });
77        }
78        capacity = capacity.saturating_mul(2).min(max_capacity);
79    }
80}