Skip to main content

flare_core/common/compression/
registry.rs

1//! 压缩器注册表
2//!
3//! 管理压缩器的注册和查找,支持用户注册自定义压缩器
4
5#[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    /// 全局压缩器注册表
16    static ref COMPRESSION_REGISTRY: CompressionRegistry = {
17        let registry = CompressionRegistry::new();
18        registry.register_defaults();
19        registry
20    };
21}
22
23/// 压缩器注册表
24///
25/// 管理压缩器的注册和查找
26pub struct CompressionRegistry {
27    compressors: Arc<RwLock<HashMap<String, Arc<dyn Compressor>>>>,
28}
29
30impl CompressionRegistry {
31    /// 创建新的注册表
32    pub fn new() -> Self {
33        Self {
34            compressors: Arc::new(RwLock::new(HashMap::new())),
35        }
36    }
37
38    /// 注册内置压缩器
39    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    /// 注册压缩器
46    ///
47    /// # 参数
48    /// - `name`: 压缩器名称(用于查找)
49    /// - `compressor`: 压缩器实例
50    ///
51    /// # 示例
52    ///
53    /// ```rust,ignore
54    /// use flare_core::common::compression::{CompressionRegistry, Compressor};
55    /// use std::sync::Arc;
56    ///
57    /// struct MyCompressor;
58    /// impl Compressor for MyCompressor { /* ... */ }
59    ///
60    /// let registry = CompressionRegistry::new();
61    /// registry.register("my_custom", Arc::new(MyCompressor));
62    /// ```
63    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    /// 查找压缩器
70    ///
71    /// # 参数
72    /// - `name`: 压缩器名称
73    ///
74    /// # 返回
75    /// 找到的压缩器,如果不存在则返回 None
76    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    /// 根据算法类型查找压缩器
84    pub fn find_by_algorithm(
85        &self,
86        algorithm: CompressionAlgorithm,
87    ) -> Option<Arc<dyn Compressor>> {
88        self.find(&algorithm.as_str())
89    }
90
91    /// 检查压缩器是否已注册
92    ///
93    /// # 参数
94    /// - `name`: 压缩器名称
95    ///
96    /// # 返回
97    /// 如果已注册返回 `true`,否则返回 `false`
98    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    /// 尝试自动检测压缩算法
106    ///
107    /// 遍历所有注册的压缩器,使用 `can_detect` 方法检测
108    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    /// 获取全局注册表实例
118    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
129/// 压缩工具类
130///
131/// 提供便捷的压缩/解压方法,使用全局注册表
132pub struct CompressionUtil;
133
134impl CompressionUtil {
135    /// 根据算法类型获取压缩器
136    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    /// 根据名称获取压缩器
143    pub fn get_compressor_by_name(name: &str) -> Option<Arc<dyn Compressor>> {
144        CompressionRegistry::global().find(name)
145    }
146
147    /// 压缩数据(根据算法类型)
148    pub fn compress(data: &[u8], algorithm: CompressionAlgorithm) -> Result<Vec<u8>> {
149        let compressor = Self::get_compressor(algorithm);
150        compressor.compress(data)
151    }
152
153    /// 解压数据(根据算法类型)
154    pub fn decompress(data: &[u8], algorithm: CompressionAlgorithm) -> Result<Vec<u8>> {
155        let compressor = Self::get_compressor(algorithm);
156        compressor.decompress(data)
157    }
158
159    /// 检查压缩器是否已注册
160    ///
161    /// # 参数
162    /// - `name`: 压缩器名称
163    ///
164    /// # 返回
165    /// 如果已注册返回 `true`,否则返回 `false`
166    pub fn is_registered(name: &str) -> bool {
167        CompressionRegistry::global().is_registered(name)
168    }
169
170    /// 尝试自动检测压缩算法并解压
171    ///
172    /// 首先尝试自动检测压缩算法,如果检测不到则作为无压缩处理
173    pub fn auto_decompress(data: &[u8]) -> Result<(Vec<u8>, CompressionAlgorithm)> {
174        // 尝试自动检测
175        if let Some(compressor) = CompressionRegistry::global().auto_detect(data) {
176            let decompressed = compressor.decompress(data)?;
177            return Ok((decompressed, compressor.algorithm()));
178        }
179
180        // 默认不压缩
181        Ok((data.to_vec(), CompressionAlgorithm::None))
182    }
183
184    /// 注册自定义压缩器到全局注册表
185    ///
186    /// # 示例
187    ///
188    /// ```rust,ignore
189    /// use flare_core::common::compression::{CompressionUtil, Compressor};
190    /// use std::sync::Arc;
191    ///
192    /// struct MyCompressor;
193    /// impl Compressor for MyCompressor { /* ... */ }
194    ///
195    /// CompressionUtil::register_custom(Arc::new(MyCompressor));
196    /// ```
197    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"; // Gzip 魔数
223        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"; // Gzip 魔数
235        let registry = CompressionRegistry::new();
236        registry.register_defaults();
237
238        assert!(registry.auto_detect(data).is_none());
239    }
240}