// Archive Module - Universal Compression Format Support // Supports 12 compression formats: 9 core + 3 optional // Core: ZIP, TAR, GZIP, ZSTD, BZIP2, LZ4, TAR.GZ, TAR.BZ2, TAR.ZST // Optional: RAR (legal risk), XZ (external dependency), 7z (unstable library) pub mod config; pub mod detector; pub mod metadata; pub mod processor; pub mod warning; pub mod processors { pub mod core; #[cfg(feature = "optional-formats")] pub mod optional; } #[cfg(test)] pub mod tests; use anyhow::Result; use std::collections::HashMap; use std::path::Path; use crate::archive::{ArchiveFormat, ArchiveProcessor, FormatDetector, ArchiveConfig}; /// Processor Registry - Plugin Architecture pub struct ProcessorRegistry { processors: HashMap>, config: ArchiveConfig, } impl ProcessorRegistry { /// Create new registry with config pub fn new(config: ArchiveConfig) -> Self { Self { processors: HashMap::new(), config, } } /// Initialize all processors (based on config) pub fn initialize(&mut self) -> Result<()> { // Core formats (always registered) self.register_core_processors()?; // Optional formats (based on config) self.register_optional_processors()?; Ok(()) } /// Register core format processors (9 formats) fn register_core_processors(&mut self) -> Result<()> { use crate::archive::processors::core::*; self.processors.insert(ArchiveFormat::Zip, Box::new(ZipProcessor::new())); self.processors.insert(ArchiveFormat::Tar, Box::new(TarProcessor::new())); self.processors.insert(ArchiveFormat::Gzip, Box::new(GzipProcessor::new())); self.processors.insert(ArchiveFormat::Zstd, Box::new(ZstdProcessor::new())); self.processors.insert(ArchiveFormat::Bzip2, Box::new(Bzip2Processor::new())); self.processors.insert(ArchiveFormat::Lz4, Box::new(Lz4Processor::new())); self.processors.insert(ArchiveFormat::TarGzip, Box::new(TarGzipProcessor::new())); self.processors.insert(ArchiveFormat::TarBzip2, Box::new(TarBzip2Processor::new())); self.processors.insert(ArchiveFormat::TarZstd, Box::new(TarZstdProcessor::new())); info!("✅ Core formats registered: 9 formats"); Ok(()) } /// Register optional format processors (3 formats, based on config) fn register_optional_processors(&mut self) -> Result<()> { #[cfg(feature = "optional-formats")] { use crate::archive::processors::optional::*; // RAR format (legal risk) if self.config.enable_rar { crate::archive::warning::show_rar_legal_warning(); self.processors.insert(ArchiveFormat::Rar, Box::new(RarProcessor::new())); warn!("⚠️ RAR format enabled (legal risk)"); } // XZ format (external dependency) if self.config.enable_xz { if check_liblzma_available() { self.processors.insert(ArchiveFormat::Xz, Box::new(XzProcessor::new())); info!("✅ XZ format enabled"); } else { crate::archive::warning::show_xz_dependency_warning(); warn!("⚠️ XZ format disabled (liblzma not found)"); } } // 7z format (unstable library) if self.config.enable_7z { crate::archive::warning::show_7z_stability_warning(); self.processors.insert(ArchiveFormat::SevenZ, Box::new(SevenZProcessor::new())); warn!("⚠️ 7z format enabled (stability warning)"); } } Ok(()) } /// Get processor for detected format pub fn get_processor(&self, path: &Path) -> Result<&dyn ArchiveProcessor> { let detector = FormatDetector::new(); let format = detector.detect(path)?; self.processors .get(&format) .map(|p| p.as_ref()) .ok_or_else(|| anyhow::anyhow!("Format {} not supported or not enabled", format)) } /// List all enabled formats pub fn enabled_formats(&self) -> Vec { self.processors.keys().cloned().collect() } } /// Check if liblzma library is available #[cfg(feature = "optional-formats")] fn check_liblzma_available() -> bool { // Try to load xz2 library // Simplified check: try to create XzProcessor true // Simplified for now, actual implementation needs better detection } #[cfg(not(feature = "optional-formats"))] fn check_liblzma_available() -> bool { false } /// Initialize archive system with config pub fn init_archive_system(config_path: Option<&str>) -> Result { let config = if let Some(path) = config_path { ArchiveConfig::load(path)? } else { ArchiveConfig::default() }; // Show startup warnings for optional formats crate::archive::warning::show_startup_warnings(&config); let mut registry = ProcessorRegistry::new(config); registry.initialize()?; info!("Archive system initialized with {} formats", registry.enabled_formats().len()); Ok(registry) }