use std::sync::Arc;
#[derive(Debug, Clone)]
pub enum ProgressEvent {
FetchingFeed { url: String },
FeedParsed {
podcast_title: String,
total_episodes: usize,
new_episodes: usize,
to_download: usize,
},
DownloadStarting {
download_id: usize,
episode_title: String,
episode_index: usize,
total_to_download: usize,
content_length: Option<u64>,
},
DownloadProgress {
download_id: usize,
episode_title: String,
bytes_downloaded: u64,
total_bytes: Option<u64>,
},
DownloadCompleted {
download_id: usize,
episode_title: String,
bytes_downloaded: u64,
},
DownloadFailed {
download_id: usize,
episode_title: String,
error: String,
},
Finalizing {
download_id: usize,
episode_title: String,
},
HashingCompleted {
download_id: usize,
episode_title: String,
hash: String,
},
PartialFilesCleanedUp { count: usize },
SyncCompleted {
downloaded_count: usize,
existing_count: usize,
limited_count: usize,
failed_count: usize,
},
}
pub trait ProgressReporter: Send + Sync {
fn report(&self, event: ProgressEvent);
}
pub type SharedProgressReporter = Arc<dyn ProgressReporter>;
#[derive(Debug, Default, Clone, Copy)]
pub struct NoopReporter;
impl ProgressReporter for NoopReporter {
fn report(&self, _event: ProgressEvent) {
}
}
impl NoopReporter {
pub fn shared() -> SharedProgressReporter {
Arc::new(Self)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn noop_reporter_handles_all_events() {
let reporter = NoopReporter;
reporter.report(ProgressEvent::FetchingFeed {
url: "https://example.com/feed.xml".to_string(),
});
reporter.report(ProgressEvent::FeedParsed {
podcast_title: "Test Podcast".to_string(),
total_episodes: 10,
new_episodes: 5,
to_download: 3,
});
reporter.report(ProgressEvent::DownloadStarting {
download_id: 0,
episode_title: "Episode 1".to_string(),
episode_index: 0,
total_to_download: 5,
content_length: Some(1024),
});
reporter.report(ProgressEvent::DownloadProgress {
download_id: 0,
episode_title: "Episode 1".to_string(),
bytes_downloaded: 512,
total_bytes: Some(1024),
});
reporter.report(ProgressEvent::DownloadCompleted {
download_id: 0,
episode_title: "Episode 1".to_string(),
bytes_downloaded: 1024,
});
reporter.report(ProgressEvent::DownloadFailed {
download_id: 1,
episode_title: "Episode 2".to_string(),
error: "Connection timeout".to_string(),
});
reporter.report(ProgressEvent::Finalizing {
download_id: 0,
episode_title: "Episode 1".to_string(),
});
reporter.report(ProgressEvent::HashingCompleted {
download_id: 0,
episode_title: "Episode 1".to_string(),
hash: "sha256:abc123".to_string(),
});
reporter.report(ProgressEvent::PartialFilesCleanedUp { count: 2 });
reporter.report(ProgressEvent::SyncCompleted {
downloaded_count: 4,
existing_count: 5,
limited_count: 2,
failed_count: 1,
});
}
}