flare_core/common/compression/
registry.rs1#[cfg(feature = "compression-gzip")]
6use super::algorithms::GzipCompressor;
7use super::algorithms::{CompressionAlgorithm, NoCompressor};
8use super::traits::Compressor;
9use crate::common::error::Result;
10use std::collections::HashMap;
11use std::sync::Arc;
12use std::sync::RwLock;
13
14lazy_static::lazy_static! {
15 static ref COMPRESSION_REGISTRY: CompressionRegistry = {
17 let registry = CompressionRegistry::new();
18 registry.register_defaults();
19 registry
20 };
21}
22
23pub struct CompressionRegistry {
27 compressors: Arc<RwLock<HashMap<String, Arc<dyn Compressor>>>>,
28}
29
30impl CompressionRegistry {
31 pub fn new() -> Self {
33 Self {
34 compressors: Arc::new(RwLock::new(HashMap::new())),
35 }
36 }
37
38 pub fn register_defaults(&self) {
40 self.register("none", Arc::new(NoCompressor));
41 #[cfg(feature = "compression-gzip")]
42 self.register("gzip", Arc::new(GzipCompressor));
43 }
44
45 pub fn register(&self, name: &str, compressor: Arc<dyn Compressor>) {
64 if let Ok(mut compressors) = self.compressors.write() {
65 compressors.insert(name.to_string(), compressor);
66 }
67 }
68
69 pub fn find(&self, name: &str) -> Option<Arc<dyn Compressor>> {
77 self.compressors
78 .read()
79 .ok()
80 .and_then(|compressors| compressors.get(name).map(Arc::clone))
81 }
82
83 pub fn find_by_algorithm(
85 &self,
86 algorithm: CompressionAlgorithm,
87 ) -> Option<Arc<dyn Compressor>> {
88 self.find(&algorithm.as_str())
89 }
90
91 pub fn is_registered(&self, name: &str) -> bool {
99 self.compressors
100 .read()
101 .map(|compressors| compressors.contains_key(name))
102 .unwrap_or(false)
103 }
104
105 pub fn auto_detect(&self, data: &[u8]) -> Option<Arc<dyn Compressor>> {
109 self.compressors.read().ok().and_then(|compressors| {
110 compressors
111 .values()
112 .find(|compressor| compressor.can_detect(data))
113 .map(Arc::clone)
114 })
115 }
116
117 pub fn global() -> &'static CompressionRegistry {
119 &COMPRESSION_REGISTRY
120 }
121}
122
123impl Default for CompressionRegistry {
124 fn default() -> Self {
125 Self::new()
126 }
127}
128
129pub struct CompressionUtil;
133
134impl CompressionUtil {
135 pub fn get_compressor(algorithm: CompressionAlgorithm) -> Arc<dyn Compressor> {
137 CompressionRegistry::global()
138 .find_by_algorithm(algorithm)
139 .unwrap_or_else(|| Arc::new(NoCompressor))
140 }
141
142 pub fn get_compressor_by_name(name: &str) -> Option<Arc<dyn Compressor>> {
144 CompressionRegistry::global().find(name)
145 }
146
147 pub fn compress(data: &[u8], algorithm: CompressionAlgorithm) -> Result<Vec<u8>> {
149 let compressor = Self::get_compressor(algorithm);
150 compressor.compress(data)
151 }
152
153 pub fn decompress(data: &[u8], algorithm: CompressionAlgorithm) -> Result<Vec<u8>> {
155 let compressor = Self::get_compressor(algorithm);
156 compressor.decompress(data)
157 }
158
159 pub fn is_registered(name: &str) -> bool {
167 CompressionRegistry::global().is_registered(name)
168 }
169
170 pub fn auto_decompress(data: &[u8]) -> Result<(Vec<u8>, CompressionAlgorithm)> {
174 if let Some(compressor) = CompressionRegistry::global().auto_detect(data) {
176 let decompressed = compressor.decompress(data)?;
177 return Ok((decompressed, compressor.algorithm()));
178 }
179
180 Ok((data.to_vec(), CompressionAlgorithm::None))
182 }
183
184 pub fn register_custom(compressor: Arc<dyn Compressor>) {
198 CompressionRegistry::global().register(compressor.name(), compressor);
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn test_compression_registry() {
208 let registry = CompressionRegistry::new();
209 registry.register_defaults();
210
211 assert!(registry.find("none").is_some());
212 #[cfg(feature = "compression-gzip")]
213 assert!(registry.find("gzip").is_some());
214 #[cfg(not(feature = "compression-gzip"))]
215 assert!(registry.find("gzip").is_none());
216 assert!(registry.find("unknown").is_none());
217 }
218
219 #[test]
220 #[cfg(feature = "compression-gzip")]
221 fn test_auto_detect() {
222 let data = b"\x1f\x8b\x08test"; let registry = CompressionRegistry::new();
224 registry.register_defaults();
225
226 let compressor = registry.auto_detect(data);
227 assert!(compressor.is_some());
228 assert_eq!(compressor.unwrap().algorithm(), CompressionAlgorithm::Gzip);
229 }
230
231 #[test]
232 #[cfg(not(feature = "compression-gzip"))]
233 fn test_auto_detect_without_gzip_feature() {
234 let data = b"\x1f\x8b\x08test"; let registry = CompressionRegistry::new();
236 registry.register_defaults();
237
238 assert!(registry.auto_detect(data).is_none());
239 }
240}