use serde::{
Deserialize,
Serialize,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct ProgressCounter {
metric_id: String,
total_count: Option<u64>,
completed_count: u64,
active_count: u64,
succeeded_count: u64,
failed_count: u64,
}
impl ProgressCounter {
#[inline]
pub fn new(metric_id: &str) -> Self {
Self {
metric_id: metric_id.to_owned(),
total_count: None,
completed_count: 0,
active_count: 0,
succeeded_count: 0,
failed_count: 0,
}
}
#[inline]
#[must_use]
pub const fn with_total_count(mut self, total_count: Option<u64>) -> Self {
self.total_count = total_count;
self
}
#[inline]
#[must_use]
pub const fn total(self, total_count: u64) -> Self {
self.with_total_count(Some(total_count))
}
#[inline]
#[must_use]
pub const fn unknown_total(self) -> Self {
self.with_total_count(None)
}
#[inline]
#[must_use]
pub const fn with_completed_count(mut self, completed_count: u64) -> Self {
self.completed_count = completed_count;
self
}
#[inline]
#[must_use]
pub const fn completed(self, completed_count: u64) -> Self {
self.with_completed_count(completed_count)
}
#[inline]
#[must_use]
pub const fn with_active_count(mut self, active_count: u64) -> Self {
self.active_count = active_count;
self
}
#[inline]
#[must_use]
pub const fn active(self, active_count: u64) -> Self {
self.with_active_count(active_count)
}
#[inline]
#[must_use]
pub const fn with_succeeded_count(mut self, succeeded_count: u64) -> Self {
self.succeeded_count = succeeded_count;
self
}
#[inline]
#[must_use]
pub const fn succeeded(self, succeeded_count: u64) -> Self {
self.with_succeeded_count(succeeded_count)
}
#[inline]
#[must_use]
pub const fn with_failed_count(mut self, failed_count: u64) -> Self {
self.failed_count = failed_count;
self
}
#[inline]
#[must_use]
pub const fn failed(self, failed_count: u64) -> Self {
self.with_failed_count(failed_count)
}
#[inline]
pub fn metric_id(&self) -> &str {
self.metric_id.as_str()
}
#[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)
}
}