Skip to main content

dspk_core/
progress.rs

1//! Progress of long runs (a sorter over a recording, a pyramid build, …). Libraries only report
2//! ([`ProgressSink`]); entry points draw it (a Python bar, a terminal bar) and estimate the time
3//! left from the rate.
4
5/// Where a run is: stage `step` of `steps` (1-based), named `stage`, with `done` of `total` units
6/// of its work finished (`total` 0: unknown).
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub struct ProgressEvent<'a> {
9    pub stage: &'a str,
10    pub step: usize,
11    pub steps: usize,
12    pub done: u64,
13    pub total: u64,
14    /// What `done` counts (e.g. `"windows"`, `"samples"`).
15    pub unit: &'a str,
16}
17
18/// Receives the progress of a run. Called from the run's thread; keep it short.
19pub trait ProgressSink: Send + Sync {
20    fn report(&self, event: &ProgressEvent<'_>);
21}
22
23/// Ignores progress.
24#[derive(Debug, Clone, Copy, Default)]
25pub struct NoProgress;
26
27impl ProgressSink for NoProgress {
28    fn report(&self, _event: &ProgressEvent<'_>) {}
29}
30
31impl<F: Fn(&ProgressEvent<'_>) + Send + Sync> ProgressSink for F {
32    fn report(&self, event: &ProgressEvent<'_>) {
33        self(event)
34    }
35}
36
37/// The stages of one run, numbered in order: reports through `sink` as
38/// `stages.report(index, done, total)`.
39#[derive(Clone, Copy)]
40pub struct Stages<'a> {
41    sink: &'a dyn ProgressSink,
42    names: &'a [(&'a str, &'a str)],
43}
44
45impl<'a> Stages<'a> {
46    /// `names`: `(stage, unit)` of every stage, in order.
47    pub fn new(sink: &'a dyn ProgressSink, names: &'a [(&'a str, &'a str)]) -> Self {
48        Self { sink, names }
49    }
50
51    /// Reports `done` of `total` for stage `name` (ignored when the run has no such stage).
52    pub fn report(&self, name: &str, done: u64, total: u64) {
53        if let Some(i) = self.names.iter().position(|(n, _)| *n == name) {
54            let (stage, unit) = self.names[i];
55            self.sink.report(&ProgressEvent { stage, step: i + 1, steps: self.names.len(), done, total, unit });
56        }
57    }
58}