prodash/progress/
mod.rs

1use std::{
2    sync::{
3        atomic::{AtomicUsize, Ordering},
4        Arc,
5    },
6    time::SystemTime,
7};
8
9use crate::unit::Unit;
10
11///
12pub mod key;
13#[doc(inline)]
14pub use key::Key;
15
16mod utils;
17
18#[cfg(feature = "progress-log")]
19mod log;
20pub use utils::{Discard, DoOrDiscard, Either, ThroughputOnDrop};
21
22#[cfg(feature = "progress-log")]
23pub use self::log::Log;
24
25/// Four bytes of function-local unique and stable identifier for each item added as progress,
26/// like b"TREE" or b"FILE".
27///
28/// Note that uniqueness only relates to one particular method call where those interested in its progress
29/// may assume certain stable ids to look for when selecting specific bits of progress to process.
30pub type Id = [u8; 4];
31
32/// The default Id to use if there is no need for an id.
33///
34/// This is the default unless applications wish to make themselves more introspectable.
35pub const UNKNOWN: Id = *b"\0\0\0\0";
36
37/// The amount of steps a progress can make
38pub type Step = usize;
39
40/// The amount of steps a progress can make, for threadsafe counting.
41pub type AtomicStep = AtomicUsize;
42
43/// As step, but shareable.
44pub type StepShared = Arc<AtomicStep>;
45
46/// Indicate whether a progress can or cannot be made.
47#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Debug, Hash)]
48pub enum State {
49    /// Indicates a task is blocked and cannot indicate progress, optionally until the
50    /// given time. The task cannot easily be interrupted.
51    Blocked(&'static str, Option<SystemTime>),
52    /// Indicates a task cannot indicate progress, optionally until the
53    /// given time. The task can be interrupted.
54    Halted(&'static str, Option<SystemTime>),
55    /// The task is running
56    #[default]
57    Running,
58}
59
60/// Progress associated with some item in the progress tree.
61#[derive(Clone, Default, Debug)]
62pub struct Value {
63    /// The amount of progress currently made
64    pub step: StepShared,
65    /// The step at which no further progress has to be made.
66    ///
67    /// If unset, the progress is unbounded.
68    pub done_at: Option<Step>,
69    /// The unit associated with the progress.
70    pub unit: Option<Unit>,
71    /// Whether progress can be made or not
72    pub state: State,
73}
74
75impl std::hash::Hash for Value {
76    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
77        let Self {
78            step,
79            done_at,
80            unit,
81            state: our_state,
82        } = self;
83        done_at.hash(state);
84        unit.hash(state);
85        our_state.hash(state);
86        step.load(Ordering::Relaxed).hash(state);
87    }
88}
89
90impl Value {
91    /// Returns a number between `Some(0.0)` and `Some(1.0)`, or `None` if the progress is unbounded.
92    ///
93    /// A task half done would return `Some(0.5)`.
94    pub fn fraction(&self) -> Option<f32> {
95        self.done_at
96            .map(|done_at| self.step.load(Ordering::SeqCst) as f32 / done_at as f32)
97    }
98}
99
100/// The value associated with a spot in the hierarchy.
101#[derive(Clone, Default, Debug, Hash)]
102pub struct Task {
103    /// The name of the `Item` or task.
104    pub name: String,
105    /// The stable identifier of this task.
106    /// Useful for selecting specific tasks out of a set of them.
107    pub id: Id,
108    /// The progress itself, unless this value belongs to an `Item` serving as organizational unit.
109    pub progress: Option<Value>,
110}