mod state;
mod worker;
use std::{
fmt::Debug,
sync::{Arc, atomic::Ordering},
};
use num_traits::AsPrimitive;
use crate::progress::{state::ProgressState, worker::ProgressWorker};
pub struct Progress {
state: Arc<ProgressState>,
worker: ProgressWorker,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ProgressTag {
Tps,
Dps,
Eta,
Time,
}
impl Progress {
#[must_use]
pub fn new(total: impl AsPrimitive<u64>) -> Self {
let total = total.as_();
assert_ne!(total, 0, "Total cannot be zero.");
let state = Arc::new(ProgressState::new(total));
let worker = ProgressWorker::new(state.clone());
Progress {
state,
worker,
}
}
#[inline]
pub fn set_width(&self, width: impl AsPrimitive<u64>) {
let width = width.as_();
assert_ne!(width, 0, "Width cannot be zero.");
self.state.width.store(width, Ordering::Relaxed);
}
#[inline]
#[must_use]
pub fn with_width(self, width: impl AsPrimitive<u64>) -> Self {
self.set_width(width);
self
}
#[inline]
pub fn set_filled_character(&self, filled_character: char) {
self.state
.filled_character
.store(filled_character as u8, Ordering::Relaxed);
}
#[inline]
#[must_use]
pub fn with_filled_character(self, filled_character: char) -> Self {
self.set_filled_character(filled_character);
self
}
#[inline]
pub fn set_current_character(&self, curr_character: char) {
self.state
.curr_character
.store(curr_character as u8, Ordering::Relaxed);
}
#[inline]
#[must_use]
pub fn with_current_character(self, current_character: char) -> Self {
self.set_current_character(current_character);
self
}
#[inline]
pub fn set_remaining_character(&self, remaining_character: char) {
self.state
.remaining_character
.store(remaining_character as u8, Ordering::Relaxed);
}
#[inline]
#[must_use]
pub fn with_remaining_character(self, remaining_character: char) -> Self {
self.set_remaining_character(remaining_character);
self
}
#[inline]
pub fn set_tag(&mut self, tag: ProgressTag) {
assert!(
!self.state.tags.read().contains(&tag),
"Progress tag {tag:?} is already enabled.",
);
self.state.tags.write().push(tag);
}
#[inline]
#[must_use]
pub fn with_tag(mut self, tag: ProgressTag) -> Self {
self.set_tag(tag);
self
}
#[inline]
#[must_use]
pub fn is_complete(&self) -> bool {
self.state.is_complete()
}
#[inline]
pub fn tick(&mut self, value: impl AsPrimitive<u64>) {
self.state
.curr
.fetch_add(value.as_(), Ordering::Relaxed);
}
#[inline]
pub fn stop(&mut self) {
self.state.stopped.store(true, Ordering::Relaxed);
}
}
impl Drop for Progress {
fn drop(&mut self) {
if let Some(thread) = self.worker.thread.take() {
let _ = thread.join();
}
}
}