cadmpeg_core/decode/
deflate.rs1use super::{DecodeContext, View};
5use crate::CodecError;
6use flate2::{Decompress, FlushDecompress, Status};
7
8impl DecodeContext<'_> {
9 pub fn inflate_probe(
12 &self,
13 source: View<'_>,
14 cap: usize,
15 zlib: bool,
16 ) -> Result<Option<Vec<u8>>, CodecError> {
17 if let Some(limit) = self.resource_refusal() {
18 return Err(CodecError::ResourceLimit(limit));
19 }
20 let mut decoder = Decompress::new(zlib);
21 let mut output = Vec::new();
22 let mut chunk = [0_u8; 1024];
23 let mut offset = 0;
24 loop {
25 let before_in = decoder.total_in();
26 let before_out = decoder.total_out();
27 let Ok(status) = decoder.decompress(
28 &source.window()[offset..],
29 &mut chunk,
30 FlushDecompress::None,
31 ) else {
32 return Ok(None);
33 };
34 let consumed = usize::try_from(decoder.total_in() - before_in)
35 .map_err(|_| CodecError::Malformed("DEFLATE probe input overflow".into()))?;
36 let produced = usize::try_from(decoder.total_out() - before_out)
37 .map_err(|_| CodecError::Malformed("DEFLATE probe output overflow".into()))?;
38 offset += consumed;
39 if cap
40 .checked_sub(output.len())
41 .is_none_or(|remaining| produced > remaining)
42 {
43 return Ok(None);
44 }
45 output.extend_from_slice(&chunk[..produced]);
46 if status == Status::StreamEnd || (consumed == 0 && produced == 0) {
47 return Ok(Some(output));
48 }
49 }
50 }
51}