Skip to main content

qubit_progress/model/
progress_event_builder.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use std::time::Duration;
11
12use super::{
13    ProgressCounters,
14    ProgressEvent,
15    ProgressPhase,
16    ProgressStage,
17};
18
19/// Builder for [`ProgressEvent`].
20///
21/// The builder keeps the common path compact by letting callers configure
22/// phase, counters, optional stage information, and elapsed time in a single
23/// chain.
24#[derive(Debug, Clone, PartialEq)]
25pub struct ProgressEventBuilder {
26    /// Lifecycle phase of the event being built.
27    pub(crate) phase: ProgressPhase,
28    /// Generic counters for the event being built.
29    pub(crate) counters: ProgressCounters,
30    /// Optional current stage.
31    pub(crate) stage: Option<ProgressStage>,
32    /// Monotonic elapsed duration.
33    pub(crate) elapsed: Duration,
34}
35
36impl ProgressEventBuilder {
37    /// Creates a builder with default running progress state.
38    ///
39    /// # Returns
40    ///
41    /// A builder whose phase is [`ProgressPhase::Running`], elapsed duration is
42    /// zero, total count is unknown, and all counters are zero.
43    #[inline]
44    pub const fn new() -> Self {
45        Self {
46            phase: ProgressPhase::Running,
47            counters: ProgressCounters::new(None),
48            stage: None,
49            elapsed: Duration::ZERO,
50        }
51    }
52
53    /// Configures the lifecycle phase.
54    ///
55    /// # Parameters
56    ///
57    /// * `phase` - Lifecycle phase to report.
58    ///
59    /// # Returns
60    ///
61    /// This builder with `phase` recorded.
62    #[inline]
63    pub const fn phase(mut self, phase: ProgressPhase) -> Self {
64        self.phase = phase;
65        self
66    }
67
68    /// Configures the event as started.
69    ///
70    /// # Returns
71    ///
72    /// This builder with [`ProgressPhase::Started`].
73    #[inline]
74    pub const fn started(self) -> Self {
75        self.phase(ProgressPhase::Started)
76    }
77
78    /// Configures the event as running.
79    ///
80    /// # Returns
81    ///
82    /// This builder with [`ProgressPhase::Running`].
83    #[inline]
84    pub const fn running(self) -> Self {
85        self.phase(ProgressPhase::Running)
86    }
87
88    /// Configures the event as finished.
89    ///
90    /// # Returns
91    ///
92    /// This builder with [`ProgressPhase::Finished`].
93    #[inline]
94    pub const fn finished(self) -> Self {
95        self.phase(ProgressPhase::Finished)
96    }
97
98    /// Configures the event as failed.
99    ///
100    /// # Returns
101    ///
102    /// This builder with [`ProgressPhase::Failed`].
103    #[inline]
104    pub const fn failed(self) -> Self {
105        self.phase(ProgressPhase::Failed)
106    }
107
108    /// Configures the event as canceled.
109    ///
110    /// # Returns
111    ///
112    /// This builder with [`ProgressPhase::Canceled`].
113    #[inline]
114    pub const fn canceled(self) -> Self {
115        self.phase(ProgressPhase::Canceled)
116    }
117
118    /// Replaces the current counter set.
119    ///
120    /// # Parameters
121    ///
122    /// * `counters` - Complete counter set to carry in the built event.
123    ///
124    /// # Returns
125    ///
126    /// This builder with `counters` recorded.
127    #[inline]
128    pub const fn counters(mut self, counters: ProgressCounters) -> Self {
129        self.counters = counters;
130        self
131    }
132
133    /// Configures a known total work-unit count.
134    ///
135    /// # Parameters
136    ///
137    /// * `total_count` - Total number of work units.
138    ///
139    /// # Returns
140    ///
141    /// This builder with a known total count.
142    #[inline]
143    pub const fn total(mut self, total_count: usize) -> Self {
144        self.counters = self.counters.with_total_count(Some(total_count));
145        self
146    }
147
148    /// Configures the event as unknown-total progress.
149    ///
150    /// # Returns
151    ///
152    /// This builder with no total count.
153    #[inline]
154    pub const fn unknown_total(mut self) -> Self {
155        self.counters = self.counters.with_total_count(None);
156        self
157    }
158
159    /// Configures the completed work-unit count.
160    ///
161    /// # Parameters
162    ///
163    /// * `completed_count` - Number of completed work units.
164    ///
165    /// # Returns
166    ///
167    /// This builder with `completed_count` recorded.
168    #[inline]
169    pub const fn completed(mut self, completed_count: usize) -> Self {
170        self.counters = self.counters.with_completed_count(completed_count);
171        self
172    }
173
174    /// Configures the active work-unit count.
175    ///
176    /// # Parameters
177    ///
178    /// * `active_count` - Number of currently active work units.
179    ///
180    /// # Returns
181    ///
182    /// This builder with `active_count` recorded.
183    #[inline]
184    pub const fn active(mut self, active_count: usize) -> Self {
185        self.counters = self.counters.with_active_count(active_count);
186        self
187    }
188
189    /// Configures the successful work-unit count.
190    ///
191    /// # Parameters
192    ///
193    /// * `succeeded_count` - Number of successful work units.
194    ///
195    /// # Returns
196    ///
197    /// This builder with `succeeded_count` recorded.
198    #[inline]
199    pub const fn succeeded(mut self, succeeded_count: usize) -> Self {
200        self.counters = self.counters.with_succeeded_count(succeeded_count);
201        self
202    }
203
204    /// Configures the failed work-unit count.
205    ///
206    /// # Parameters
207    ///
208    /// * `failed_count` - Number of failed work units.
209    ///
210    /// # Returns
211    ///
212    /// This builder with `failed_count` recorded.
213    #[inline]
214    pub const fn failed_count(mut self, failed_count: usize) -> Self {
215        self.counters = self.counters.with_failed_count(failed_count);
216        self
217    }
218
219    /// Configures the current stage.
220    ///
221    /// # Parameters
222    ///
223    /// * `stage` - Stage metadata to carry in the built event.
224    ///
225    /// # Returns
226    ///
227    /// This builder with `stage` recorded.
228    #[inline]
229    pub fn stage(mut self, stage: ProgressStage) -> Self {
230        self.stage = Some(stage);
231        self
232    }
233
234    /// Configures the current stage from an id and display name.
235    ///
236    /// # Parameters
237    ///
238    /// * `id` - Stable machine-readable stage identifier.
239    /// * `name` - Human-readable stage name.
240    ///
241    /// # Returns
242    ///
243    /// This builder with a stage created from `id` and `name`.
244    #[inline]
245    pub fn stage_named(self, id: &str, name: &str) -> Self {
246        self.stage(ProgressStage::new(id, name))
247    }
248
249    /// Configures the elapsed duration.
250    ///
251    /// # Parameters
252    ///
253    /// * `elapsed` - Monotonic elapsed duration to carry in the event.
254    ///
255    /// # Returns
256    ///
257    /// This builder with `elapsed` recorded.
258    #[inline]
259    pub const fn elapsed(mut self, elapsed: Duration) -> Self {
260        self.elapsed = elapsed;
261        self
262    }
263
264    /// Builds the progress event.
265    ///
266    /// # Returns
267    ///
268    /// An immutable [`ProgressEvent`] with the configured values.
269    #[inline]
270    pub fn build(self) -> ProgressEvent {
271        ProgressEvent::new(self)
272    }
273}
274
275impl Default for ProgressEventBuilder {
276    /// Creates a builder with default running progress state.
277    ///
278    /// # Returns
279    ///
280    /// A builder equivalent to [`Self::new`].
281    #[inline]
282    fn default() -> Self {
283        Self::new()
284    }
285}