streaming_crypto/core_api/compression/codecs/
deflate.rs1use std::io::Read;
4use std::io::Write;
5use flate2::{Compression, write::ZlibEncoder, read::ZlibDecoder};
6
7use crate::compression::compute_checksum;
8use crate::compression::types::{Compressor, Decompressor, CompressionError};
9use crate::compression::verify_checksum;
10
11pub struct DeflateCompressor {
12 level: Compression,
13}
14
15impl DeflateCompressor {
16 pub fn new(level: i32) -> Result<Box<dyn Compressor + Send>, CompressionError> {
17 let lvl = match level {
18 0..=9 => Compression::new(level as u32),
19 _ => Compression::default(),
20 };
21 Ok(Box::new(Self { level: lvl }))
22 }
23}
24
25impl Compressor for DeflateCompressor {
26 fn compress_chunk(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<(), CompressionError> {
27 let mut enc = ZlibEncoder::new(Vec::new(), self.level);
29 enc.write_all(input)
30 .map_err(|e| CompressionError::CodecProcessFailed { codec: "deflate".into(), msg: e.to_string() })?;
31 let compressed = enc.finish()
32 .map_err(|e| CompressionError::CodecProcessFailed { codec: "deflate".into(), msg: e.to_string() })?;
33
34 let orig_len = input.len() as u32;
36 out.extend_from_slice(&orig_len.to_le_bytes());
37 out.extend_from_slice(&compressed);
38
39 let checksum = compute_checksum(&input, None);
41 out.extend_from_slice(&checksum.to_le_bytes());
42
43 Ok(())
44 }
45
46 fn finish(&mut self, _out: &mut Vec<u8>) -> Result<(), CompressionError> {
47 Ok(())
49 }
50}
51
52pub struct DeflateDecompressor;
53
54impl DeflateDecompressor {
55 pub fn new() -> Result<Box<dyn Decompressor + Send>, CompressionError> {
56 Ok(Box::new(Self))
57 }
58}
59
60impl Decompressor for DeflateDecompressor {
61 fn decompress_chunk(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<(), CompressionError> {
62 if input.len() < 8 {
63 return Err(CompressionError::CodecProcessFailed {
64 codec: "deflate".into(),
65 msg: "input too short for length+checksum prefix".into(),
66 });
67 }
68
69 let orig_len = u32::from_le_bytes(input[0..4].try_into().unwrap()) as usize;
71
72 let compressed = &input[4..input.len() - 4];
74 let checksum_bytes = &input[input.len() - 4..];
75 let expected_crc = u32::from_le_bytes(checksum_bytes.try_into().unwrap());
76
77 let mut dec = ZlibDecoder::new(compressed);
79 let mut decompressed = Vec::new();
80 dec.read_to_end(&mut decompressed)
81 .map_err(|e| CompressionError::CodecProcessFailed { codec: "deflate".into(), msg: e.to_string() })?;
82
83 if decompressed.len() != orig_len {
85 return Err(CompressionError::CodecProcessFailed {
86 codec: "deflate".into(),
87 msg: format!("decoded size {} != prefix {}", decompressed.len(), orig_len),
88 });
89 }
90
91 let actual_crc = compute_checksum(&decompressed, None);
93 verify_checksum(expected_crc, actual_crc, "deflate".into())?;
94
95 out.extend_from_slice(&decompressed);
96 Ok(())
97 }
98}