use std::path::Path;
use std::time::Duration;
#[derive(Debug, Clone, Default)]
pub struct ExtractionReport {
pub files_extracted: usize,
pub directories_created: usize,
pub symlinks_created: usize,
pub bytes_written: u64,
pub duration: Duration,
pub files_skipped: usize,
pub warnings: Vec<String>,
}
impl ExtractionReport {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn add_warning(&mut self, message: String) {
self.warnings.push(message);
}
#[must_use]
pub fn total_items(&self) -> usize {
self.files_extracted + self.directories_created + self.symlinks_created
}
#[must_use]
pub fn has_warnings(&self) -> bool {
!self.warnings.is_empty()
}
}
pub trait ProgressCallback: Send {
fn on_entry_start(&mut self, path: &Path, total: usize, current: usize);
fn on_bytes_written(&mut self, bytes: u64);
fn on_entry_complete(&mut self, path: &Path);
fn on_complete(&mut self);
}
#[derive(Debug, Default)]
pub struct NoopProgress;
impl ProgressCallback for NoopProgress {
fn on_entry_start(&mut self, _path: &Path, _total: usize, _current: usize) {}
fn on_bytes_written(&mut self, _bytes: u64) {}
fn on_entry_complete(&mut self, _path: &Path) {}
fn on_complete(&mut self) {}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_report() {
let report = ExtractionReport::new();
assert_eq!(report.files_extracted, 0);
assert_eq!(report.directories_created, 0);
assert_eq!(report.bytes_written, 0);
assert!(!report.has_warnings());
}
#[test]
fn test_add_warning() {
let mut report = ExtractionReport::new();
report.add_warning("Test warning".to_string());
assert!(report.has_warnings());
assert_eq!(report.warnings.len(), 1);
}
#[test]
fn test_total_items() {
let mut report = ExtractionReport::new();
report.files_extracted = 10;
report.directories_created = 5;
report.symlinks_created = 2;
assert_eq!(report.total_items(), 17);
}
}