qualia_core_db/specialized_libs/statistical_computing/
compression.rs1use super::*;
2
3pub struct DataCompressionEngine {
5 compression_algorithms: Vec<CompressionAlgorithm>,
6 compression_statistics: CompressionStatistics,
7}
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11pub enum CompressionAlgorithm {
12 Gzip,
13 LZ4,
14 ZSTD,
15 Snappy,
16 Custom(String),
17}
18
19#[derive(Debug, Clone)]
27pub struct CompressionStatistics {
28 pub original_size: u64,
30 pub compressed_size: u64,
32 pub compression_ratio: f64,
34 pub compression_time: u64,
36 pub decompression_time: u64,
38 pub compression_count: u64,
40 pub decompression_count: u64,
42}
43
44impl DataCompressionEngine {
45 pub fn new() -> Self {
46 Self {
47 compression_algorithms: vec![CompressionAlgorithm::LZ4, CompressionAlgorithm::ZSTD],
48 compression_statistics: CompressionStatistics::new(),
49 }
50 }
51
52 pub fn initialize(&mut self) -> Result<(), StatisticalError> {
53 Ok(())
54 }
55
56 pub fn compress(&mut self, data: &[u8]) -> Result<Vec<u8>, StatisticalError> {
59 let start = Instant::now();
60 let compressed = rle_compress(data);
61 let elapsed = start.elapsed().as_nanos() as u64;
62 self.compression_statistics.record_compression(
63 data.len() as u64,
64 compressed.len() as u64,
65 elapsed,
66 );
67 Ok(compressed)
68 }
69
70 pub fn decompress(&mut self, data: &[u8]) -> Result<Vec<u8>, StatisticalError> {
73 let start = Instant::now();
74 let decompressed = rle_decompress(data)?;
75 let elapsed = start.elapsed().as_nanos() as u64;
76 self.compression_statistics.record_decompression(elapsed);
77 Ok(decompressed)
78 }
79
80 pub fn get_statistics(&self) -> &CompressionStatistics {
82 &self.compression_statistics
83 }
84
85 pub fn reset_statistics(&mut self) {
87 self.compression_statistics = CompressionStatistics::new();
88 }
89
90 pub fn compression_algorithms(&self) -> &[CompressionAlgorithm] {
92 &self.compression_algorithms
93 }
94
95 pub fn add_compression_algorithm(&mut self, algorithm: CompressionAlgorithm) {
97 if !self.compression_algorithms.contains(&algorithm) {
98 self.compression_algorithms.push(algorithm);
99 }
100 }
101
102 pub fn supports_algorithm(&self, algorithm: &CompressionAlgorithm) -> bool {
104 self.compression_algorithms.contains(algorithm)
105 }
106}
107
108impl CompressionStatistics {
109 pub fn new() -> Self {
111 Self {
112 original_size: 0,
113 compressed_size: 0,
114 compression_ratio: 0.0,
115 compression_time: 0,
116 decompression_time: 0,
117 compression_count: 0,
118 decompression_count: 0,
119 }
120 }
121
122 pub fn record_compression(&mut self, original: u64, compressed: u64, elapsed_ns: u64) {
124 self.original_size += original;
125 self.compressed_size += compressed;
126 self.compression_time += elapsed_ns;
127 self.compression_count += 1;
128 self.compression_ratio = if original == 0 {
129 0.0
130 } else {
131 compressed as f64 / original as f64
132 };
133 }
134
135 pub fn record_decompression(&mut self, elapsed_ns: u64) {
137 self.decompression_time += elapsed_ns;
138 self.decompression_count += 1;
139 }
140
141 pub fn compression_ratio(&self) -> f64 {
145 if self.original_size == 0 {
146 0.0
147 } else {
148 self.compressed_size as f64 / self.original_size as f64
149 }
150 }
151
152 pub fn summary(&self) -> String {
154 format!(
155 "CompressionStatistics: {} compress op(s), {} decompress op(s), \
156 original={} bytes, compressed={} bytes, overall ratio={:.4}, \
157 last-op ratio={:.4}, compress_time={} ns, decompress_time={} ns",
158 self.compression_count,
159 self.decompression_count,
160 self.original_size,
161 self.compressed_size,
162 self.compression_ratio(),
163 self.compression_ratio,
164 self.compression_time,
165 self.decompression_time,
166 )
167 }
168}
169
170fn rle_compress(data: &[u8]) -> Vec<u8> {
175 let mut out = Vec::with_capacity(data.len());
176 let mut i = 0;
177 while i < data.len() {
178 let byte = data[i];
179 let mut count: usize = 1;
180 while i + count < data.len() && data[i + count] == byte && count < 255 {
181 count += 1;
182 }
183 out.push(count as u8);
184 out.push(byte);
185 i += count;
186 }
187 out
188}
189
190fn rle_decompress(data: &[u8]) -> Result<Vec<u8>, StatisticalError> {
192 if data.len() % 2 != 0 {
193 return Err(StatisticalError::InvalidData(
194 "Corrupted RLE stream (odd length)".to_string(),
195 ));
196 }
197 let mut out = Vec::with_capacity(data.len());
198 let mut i = 0;
199 while i < data.len() {
200 let count = data[i] as usize;
201 let byte = data[i + 1];
202 out.resize(out.len() + count, byte);
203 i += 2;
204 }
205 Ok(out)
206}