file_engine/analysis/progress.rs
1use std::path::PathBuf;
2
3use tokio::sync::mpsc;
4
5/// Deliberately a separate, smaller enum from `crate::progress::Progress`
6/// rather than a reuse: `Progress` (and the `Handle<T>` it's threaded
7/// through) live behind the `operations` feature, which `analyze`
8/// doesn't require — see `AnalysisHandle`'s doc comment for the same
9/// reasoning applied one level up.
10///
11/// `#[non_exhaustive]` for the same reason as `Progress`: adding a
12/// variant later shouldn't be a breaking change for an exhaustive match.
13#[derive(Debug, Clone)]
14#[non_exhaustive]
15pub enum AnalysisProgress {
16 /// Emitted once per matched entry (after filters, not per entry
17 /// walked) as the tree is scanned.
18 EntryAnalyzed { path: PathBuf },
19 /// Emitted once per file as it finishes content-hashing during
20 /// duplicate detection — the slow phase, so this is the only signal
21 /// of liveness while it runs. Only emitted when
22 /// `.detect_duplicates(true)` is set.
23 #[cfg(feature = "checksum")]
24 EntryHashed { path: PathBuf },
25}
26
27#[derive(Clone)]
28pub(crate) struct AnalysisProgressReporter {
29 tx: mpsc::UnboundedSender<AnalysisProgress>,
30}
31
32impl AnalysisProgressReporter {
33 pub(crate) fn new(tx: mpsc::UnboundedSender<AnalysisProgress>) -> Self {
34 Self { tx }
35 }
36
37 /// A closed receiver means nobody's listening — not a failure, just
38 /// nothing to report to. Mirrors `ProgressReporter::send`.
39 pub(crate) fn send(&self, progress: AnalysisProgress) {
40 let _ = self.tx.send(progress);
41 }
42}