Skip to main content

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}