streaming_crypto/core_api/compression/codecs/
lz4.rs1use lz4_flex::block::{compress_prepend_size, decompress_size_prepended};
4
5use crate::compression::{compute_checksum, types::{CompressionError, Compressor, Decompressor}, verify_checksum};
6
7pub struct Lz4Compressor;
11
12pub struct Lz4Decompressor;
13
14impl Lz4Compressor {
15 pub fn new(_level: i32, _dict: Option<&[u8]>) -> Result<Box<dyn Compressor + Send>, CompressionError> {
16 Ok(Box::new(Self))
18 }
19}
20
21impl Compressor for Lz4Compressor {
22 fn compress_chunk(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<(), CompressionError> {
23 let compressed = compress_prepend_size(input);
24 out.extend_from_slice(&compressed);
25
26 let checksum = compute_checksum(&input, None);
28 out.extend_from_slice(&checksum.to_le_bytes());
29
30 Ok(())
31 }
32
33 fn finish(&mut self, _out: &mut Vec<u8>) -> Result<(), CompressionError> {
34 Ok(())
35 }
36}
37
38
39impl Lz4Decompressor {
40 pub fn new(_dict: Option<&[u8]>) -> Result<Box<dyn Decompressor + Send>, CompressionError> {
41 Ok(Box::new(Self))
42 }
43}
44
45impl Decompressor for Lz4Decompressor {
46 fn decompress_chunk(&mut self, input: &[u8], out: &mut Vec<u8>) -> Result<(), CompressionError> {
47 if input.len() < 4 {
48 return Err(CompressionError::CodecProcessFailed {
49 codec: "lz4".into(),
50 msg: "missing checksum".into(),
51 });
52 }
53
54 let (compressed, checksum_bytes) = input.split_at(input.len() - 4);
56 let expected_crc = u32::from_le_bytes(checksum_bytes.try_into().unwrap());
57
58 let decompressed = decompress_size_prepended(compressed)
59 .map_err(|e| CompressionError::CodecProcessFailed {
60 codec: "lz4".into(),
61 msg: e.to_string(),
62 })?;
63
64 let actual_crc = compute_checksum(&decompressed, None);
66 verify_checksum(expected_crc, actual_crc, "lz4".into())?;
67
68 out.extend_from_slice(&decompressed);
69 Ok(())
70 }
71}