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}