use std::time::Duration;
use serde::{
Deserialize,
Serialize,
};
use super::{
ProgressCounter,
ProgressMetric,
ProgressPhase,
ProgressStage,
};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ProgressMetricSnapshot {
metric: ProgressMetric,
phase: ProgressPhase,
#[serde(skip_serializing_if = "Option::is_none")]
stage: Option<ProgressStage>,
total_count: Option<u64>,
completed_count: u64,
active_count: u64,
succeeded_count: u64,
failed_count: u64,
#[serde(with = "qubit_serde::serde::duration_with_unit")]
elapsed: Duration,
}
impl ProgressMetricSnapshot {
#[inline]
pub fn new(
metric: ProgressMetric,
phase: ProgressPhase,
stage: Option<ProgressStage>,
counter: &ProgressCounter,
elapsed: Duration,
) -> Self {
Self {
metric,
phase,
stage,
total_count: counter.total_count(),
completed_count: counter.completed_count(),
active_count: counter.active_count(),
succeeded_count: counter.succeeded_count(),
failed_count: counter.failed_count(),
elapsed,
}
}
#[inline]
pub const fn metric(&self) -> &ProgressMetric {
&self.metric
}
#[inline]
pub fn metric_id(&self) -> &str {
self.metric.id()
}
#[inline]
pub fn metric_name(&self) -> &str {
self.metric.name()
}
#[inline]
pub const fn phase(&self) -> ProgressPhase {
self.phase
}
#[inline]
pub const fn stage(&self) -> Option<&ProgressStage> {
self.stage.as_ref()
}
#[inline]
pub const fn total_count(&self) -> Option<u64> {
self.total_count
}
#[inline]
pub const fn completed_count(&self) -> u64 {
self.completed_count
}
#[inline]
pub const fn active_count(&self) -> u64 {
self.active_count
}
#[inline]
pub const fn succeeded_count(&self) -> u64 {
self.succeeded_count
}
#[inline]
pub const fn failed_count(&self) -> u64 {
self.failed_count
}
#[inline]
pub const fn remaining_count(&self) -> Option<u64> {
match self.total_count {
Some(total_count) => Some(
total_count
.saturating_sub(self.completed_count)
.saturating_sub(self.active_count),
),
None => None,
}
}
#[inline]
pub fn progress_fraction(&self) -> Option<f64> {
self.total_count.map(|total_count| {
if total_count == 0 {
1.0
} else {
(self.completed_count as f64 / total_count as f64).clamp(0.0, 1.0)
}
})
}
#[inline]
pub fn progress_percent(&self) -> Option<f64> {
self.progress_fraction().map(|fraction| fraction * 100.0)
}
#[inline]
pub const fn elapsed(&self) -> Duration {
self.elapsed
}
}