use std::time::Duration;
#[derive(Debug, Clone, Default)]
pub struct CreationReport {
pub files_added: usize,
pub directories_added: usize,
pub symlinks_added: usize,
pub bytes_written: u64,
pub bytes_compressed: u64,
pub duration: Duration,
pub files_skipped: usize,
pub warnings: Vec<String>,
}
impl CreationReport {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn add_warning(&mut self, msg: impl Into<String>) {
self.warnings.push(msg.into());
}
#[must_use]
pub fn has_warnings(&self) -> bool {
!self.warnings.is_empty()
}
#[must_use]
pub fn compression_ratio(&self) -> f64 {
if self.bytes_compressed == 0 || self.bytes_written == 0 {
return 0.0;
}
self.bytes_written as f64 / self.bytes_compressed as f64
}
#[must_use]
pub fn compression_percentage(&self) -> f64 {
if self.bytes_written == 0 {
return 0.0;
}
if self.bytes_compressed == 0 {
return 100.0;
}
let saved = self.bytes_written.saturating_sub(self.bytes_compressed);
(saved as f64 / self.bytes_written as f64) * 100.0
}
#[must_use]
pub fn total_items(&self) -> usize {
self.files_added + self.directories_added + self.symlinks_added
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_creation_report_default() {
let report = CreationReport::default();
assert_eq!(report.files_added, 0);
assert_eq!(report.directories_added, 0);
assert_eq!(report.symlinks_added, 0);
assert_eq!(report.bytes_written, 0);
assert_eq!(report.bytes_compressed, 0);
assert_eq!(report.duration, Duration::default());
assert_eq!(report.files_skipped, 0);
assert!(report.warnings.is_empty());
assert!(!report.has_warnings());
}
#[test]
fn test_creation_report_new() {
let report = CreationReport::new();
assert_eq!(report.files_added, 0);
assert!(!report.has_warnings());
}
#[test]
#[allow(clippy::float_cmp)]
fn test_creation_report_compression_ratio() {
let mut report = CreationReport::new();
report.bytes_written = 1000;
report.bytes_compressed = 500;
assert_eq!(report.compression_ratio(), 2.0);
report.bytes_written = 1000;
report.bytes_compressed = 1000;
assert_eq!(report.compression_ratio(), 1.0);
report.bytes_written = 500;
report.bytes_compressed = 1000;
assert_eq!(report.compression_ratio(), 0.5);
report.bytes_written = 1000;
report.bytes_compressed = 0;
assert_eq!(report.compression_ratio(), 0.0);
report.bytes_written = 0;
report.bytes_compressed = 500;
assert_eq!(report.compression_ratio(), 0.0);
report.bytes_written = 0;
report.bytes_compressed = 0;
assert_eq!(report.compression_ratio(), 0.0);
}
#[test]
#[allow(clippy::float_cmp)]
fn test_creation_report_compression_percentage() {
let mut report = CreationReport::new();
report.bytes_written = 1000;
report.bytes_compressed = 500;
assert_eq!(report.compression_percentage(), 50.0);
report.bytes_written = 1000;
report.bytes_compressed = 250;
assert_eq!(report.compression_percentage(), 75.0);
report.bytes_written = 1000;
report.bytes_compressed = 1000;
assert_eq!(report.compression_percentage(), 0.0);
report.bytes_written = 500;
report.bytes_compressed = 1000;
assert_eq!(report.compression_percentage(), 0.0);
report.bytes_written = 1000;
report.bytes_compressed = 0;
assert_eq!(report.compression_percentage(), 100.0);
report.bytes_written = 0;
report.bytes_compressed = 500;
assert_eq!(report.compression_percentage(), 0.0);
report.bytes_written = 0;
report.bytes_compressed = 0;
assert_eq!(report.compression_percentage(), 0.0);
}
#[test]
fn test_creation_report_warnings() {
let mut report = CreationReport::new();
assert!(!report.has_warnings());
report.add_warning("Warning 1");
assert!(report.has_warnings());
assert_eq!(report.warnings.len(), 1);
assert_eq!(report.warnings[0], "Warning 1");
report.add_warning("Warning 2".to_string());
assert_eq!(report.warnings.len(), 2);
assert_eq!(report.warnings[1], "Warning 2");
let string_ref = String::from("Warning 3");
report.add_warning(&string_ref);
assert_eq!(report.warnings.len(), 3);
}
#[test]
fn test_creation_report_total_items() {
let mut report = CreationReport::new();
assert_eq!(report.total_items(), 0);
report.files_added = 10;
report.directories_added = 5;
report.symlinks_added = 2;
assert_eq!(report.total_items(), 17);
report.files_added = 0;
assert_eq!(report.total_items(), 7);
}
#[test]
fn test_creation_report_real_scenario() {
let mut report = CreationReport::new();
report.files_added = 100;
report.directories_added = 20;
report.symlinks_added = 5;
report.bytes_written = 10 * 1024 * 1024; report.bytes_compressed = 3 * 1024 * 1024; report.duration = Duration::from_secs(2);
report.files_skipped = 3;
report.add_warning("Skipped 3 files due to size limit");
assert_eq!(report.total_items(), 125);
assert!(report.has_warnings());
assert_eq!(report.warnings.len(), 1);
let ratio = report.compression_ratio();
assert!((ratio - 3.333).abs() < 0.01);
let percentage = report.compression_percentage();
assert!((percentage - 70.0).abs() < 0.1);
}
}