use std::path::Path;
use crate::ExtractionOptions;
use crate::ExtractionReport;
use crate::ProgressCallback;
use crate::Result;
use crate::SecurityConfig;
use crate::creation::CreationConfig;
use crate::creation::CreationReport;
use crate::inspection::ArchiveManifest;
use crate::inspection::VerificationReport;
pub trait ArchiveFormat {
fn extract(
&mut self,
output_dir: &Path,
config: &SecurityConfig,
options: &ExtractionOptions,
progress: &mut dyn ProgressCallback,
) -> Result<ExtractionReport>;
fn list(&mut self, config: &SecurityConfig) -> Result<ArchiveManifest>;
fn verify(&mut self, config: &SecurityConfig) -> Result<VerificationReport>;
fn format_name(&self) -> &'static str;
}
pub trait FormatCreator {
fn create(
&self,
output: &Path,
sources: &[&Path],
config: &CreationConfig,
progress: &mut dyn ProgressCallback,
) -> Result<CreationReport>;
fn format_name(&self) -> &'static str;
}
#[cfg(test)]
mod tests {
use super::*;
struct TestFormat;
impl ArchiveFormat for TestFormat {
fn extract(
&mut self,
_output_dir: &Path,
_config: &SecurityConfig,
_options: &ExtractionOptions,
_progress: &mut dyn ProgressCallback,
) -> Result<ExtractionReport> {
Ok(ExtractionReport::new())
}
fn list(&mut self, _config: &SecurityConfig) -> Result<ArchiveManifest> {
use crate::formats::detect::ArchiveType;
Ok(ArchiveManifest::new(ArchiveType::Tar))
}
fn verify(&mut self, config: &SecurityConfig) -> Result<VerificationReport> {
let manifest = self.list(config)?;
crate::inspection::verify::verify_manifest(&manifest, config)
}
fn format_name(&self) -> &'static str {
"test"
}
}
#[test]
fn test_trait_implementation() {
let format = TestFormat;
assert_eq!(format.format_name(), "test");
}
#[test]
#[allow(clippy::unwrap_used)]
fn test_trait_extract_returns_report() {
let mut format = TestFormat;
let temp = tempfile::TempDir::new().unwrap();
let config = SecurityConfig::default();
let options = ExtractionOptions::default();
let mut noop = crate::NoopProgress;
let report = format
.extract(temp.path(), &config, &options, &mut noop)
.unwrap();
assert_eq!(report.files_extracted, 0);
}
#[test]
#[allow(clippy::unwrap_used)]
fn test_trait_list_returns_empty_manifest() {
let mut format = TestFormat;
let config = SecurityConfig::default();
let manifest = format.list(&config).unwrap();
assert_eq!(manifest.total_entries, 0);
assert_eq!(manifest.total_size, 0);
}
#[test]
#[allow(clippy::unwrap_used)]
fn test_trait_verify_returns_clean_report_for_empty_archive() {
let mut format = TestFormat;
let config = SecurityConfig::default();
let report = format.verify(&config).unwrap();
assert_eq!(report.total_entries, 0);
assert!(report.is_safe());
}
#[test]
#[allow(clippy::unwrap_used)]
fn test_trait_list_via_dyn_dispatch() {
let mut format: Box<dyn ArchiveFormat> = Box::new(TestFormat);
let config = SecurityConfig::default();
let manifest = format.list(&config).unwrap();
assert_eq!(manifest.total_entries, 0);
}
#[test]
#[allow(clippy::unwrap_used)]
fn test_trait_verify_via_dyn_dispatch() {
let mut format: Box<dyn ArchiveFormat> = Box::new(TestFormat);
let config = SecurityConfig::default();
let report = format.verify(&config).unwrap();
assert!(report.is_safe());
}
}