use indicatif::{ProgressBar as IndiProgressBar, ProgressStyle};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::time::Duration;
pub struct AkarProgress {
inner: Option<IndiProgressBar>,
cancelled: Arc<AtomicBool>,
}
impl AkarProgress {
pub fn new(msg: &str, total: Option<u64>) -> Self {
let cancelled = Arc::new(AtomicBool::new(false));
let inner = match total {
Some(n) => {
let pb = IndiProgressBar::new(n);
pb.set_style(
ProgressStyle::default_bar()
.template("{msg} [{bar:40}] {pos}/{len} ({eta})")
.unwrap()
.progress_chars("=> "),
);
pb.set_message(msg.to_owned());
Some(pb)
}
None => {
let pb = IndiProgressBar::new_spinner();
pb.set_style(
ProgressStyle::default_spinner()
.template("{spinner:.green} {msg}")
.unwrap(),
);
pb.set_message(msg.to_owned());
pb.enable_steady_tick(Duration::from_millis(100));
Some(pb)
}
};
Self { inner, cancelled }
}
pub fn inc(&self) {
if let Some(ref pb) = self.inner {
pb.inc(1);
}
}
pub fn inc_by(&self, delta: u64) {
if let Some(ref pb) = self.inner {
pb.inc(delta);
}
}
pub fn set_pos(&self, pos: u64) {
if let Some(ref pb) = self.inner {
pb.set_position(pos);
}
}
pub fn set_message(&self, msg: &str) {
if let Some(ref pb) = self.inner {
pb.set_message(msg.to_owned());
}
}
pub fn finish(&self, msg: &str) {
if let Some(ref pb) = self.inner {
pb.finish_with_message(msg.to_owned());
}
}
pub fn abort(&self) {
if let Some(ref pb) = self.inner {
pb.abandon();
}
}
pub fn cancel(&self) {
self.cancelled.store(true, Ordering::Relaxed);
self.finish("Cancelled.");
}
pub fn is_cancelled(&self) -> bool {
self.cancelled.load(Ordering::Relaxed)
}
pub fn cancelled_flag(&self) -> Arc<AtomicBool> {
self.cancelled.clone()
}
}
impl Drop for AkarProgress {
fn drop(&mut self) {
if let Some(ref pb) = self.inner {
pb.finish_and_clear();
}
}
}