use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProcessingResult {
pub book_name: String,
pub success: bool,
pub output_path: Option<PathBuf>,
pub processing_time: f64,
pub error_message: Option<String>,
pub output_size: Option<u64>,
pub used_copy_mode: bool,
}
impl ProcessingResult {
pub fn new(book_name: String) -> Self {
Self {
book_name,
success: false,
output_path: None,
processing_time: 0.0,
error_message: None,
output_size: None,
used_copy_mode: false,
}
}
pub fn success(mut self, output_path: PathBuf, processing_time: f64, used_copy_mode: bool) -> Self {
self.success = true;
self.output_path = Some(output_path.clone());
self.processing_time = processing_time;
self.used_copy_mode = used_copy_mode;
if let Ok(metadata) = std::fs::metadata(&output_path) {
self.output_size = Some(metadata.len());
}
self
}
pub fn failure(mut self, error_message: String, processing_time: f64) -> Self {
self.success = false;
self.error_message = Some(error_message);
self.processing_time = processing_time;
self
}
pub fn output_size_mb(&self) -> Option<f64> {
self.output_size.map(|size| size as f64 / (1024.0 * 1024.0))
}
}
impl std::fmt::Display for ProcessingResult {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if self.success {
write!(
f,
"✓ {} ({:.1}s, {})",
self.book_name,
self.processing_time,
if self.used_copy_mode { "copy mode" } else { "transcode" }
)?;
if let Some(size_mb) = self.output_size_mb() {
write!(f, " - {:.1} MB", size_mb)?;
}
Ok(())
} else {
write!(
f,
"✗ {} ({:.1}s) - {}",
self.book_name,
self.processing_time,
self.error_message.as_deref().unwrap_or("Unknown error")
)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_result_success() {
let result = ProcessingResult::new("Test Book".to_string())
.success(PathBuf::from("/output/test.m4b"), 120.5, true);
assert!(result.success);
assert_eq!(result.processing_time, 120.5);
assert!(result.used_copy_mode);
assert!(result.output_path.is_some());
}
#[test]
fn test_result_failure() {
let result = ProcessingResult::new("Test Book".to_string())
.failure("FFmpeg failed".to_string(), 45.2);
assert!(!result.success);
assert_eq!(result.processing_time, 45.2);
assert_eq!(result.error_message, Some("FFmpeg failed".to_string()));
}
}