Skip to main content

streaming_crypto/core_api/compression/codecs/
auto.rs

1// ## src/compression/codecs/auto.rs
2
3//! codecs/auto.rs
4//! Pass-through codec.
5
6use crate::compression::{compute_checksum, types::{CompressionError, Compressor, Decompressor}, verify_checksum};
7
8pub struct AutoCompressor;
9pub struct AutoDecompressor;
10
11impl AutoCompressor {
12    pub fn new() -> Self { Self }
13}
14impl AutoDecompressor {
15    pub fn new() -> Self { Self }
16}
17
18impl Compressor for AutoCompressor {
19    fn compress_chunk(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<(), CompressionError> {
20        let compressed = input;
21
22        // Prefix with original plaintext length (u32, LE) — matches Zstd/LZ4-flex policy
23        let orig_len = input.len() as u32;
24        out.extend_from_slice(&orig_len.to_le_bytes());
25        out.extend_from_slice(&compressed);
26
27        // Append CRC32 of original plaintext
28        let checksum = compute_checksum(&input, None);
29        out.extend_from_slice(&checksum.to_le_bytes());
30
31        Ok(())
32    }
33    fn finish(&mut self, _out: &mut Vec<u8>) -> Result<(), CompressionError> {
34        Ok(())
35    }
36}
37
38impl Decompressor for AutoDecompressor {
39    fn decompress_chunk(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<(), CompressionError> {
40        if input.len() < 8 {
41            return Err(CompressionError::CodecProcessFailed {
42                codec: "auto".into(),
43                msg: "input too short for length+checksum prefix".into(),
44            });
45        }
46
47        // Read original length prefix
48        let orig_len = u32::from_le_bytes(input[0..4].try_into().unwrap()) as usize;
49
50        // compressed data is everything except the last 4 bytes
51        let compressed = &input[4..input.len() - 4];
52        let checksum_bytes = &input[input.len() - 4..];
53        let expected_crc = u32::from_le_bytes(checksum_bytes.try_into().unwrap());
54
55        let decompressed = compressed;
56
57        // Optional sanity check: verify decoded size matches prefix
58        if decompressed.len() != orig_len {
59            return Err(CompressionError::CodecProcessFailed {
60                codec: "auto".into(),
61                msg: format!("decoded size {} != prefix {}", decompressed.len(), orig_len),
62            });
63        }
64
65        // Verify checksum
66        let actual_crc = compute_checksum(&decompressed, None);
67        verify_checksum(expected_crc, actual_crc, "auto".into())?;
68        
69        out.extend_from_slice(&decompressed);
70        Ok(())
71    }
72}