use indicatif::{ProgressBar, ProgressStyle};
pub struct TransferProgress {
bar: ProgressBar,
enabled: bool,
}
impl TransferProgress {
pub fn with_size(total_bytes: u64, enabled: bool) -> Self {
if !enabled {
return Self {
bar: ProgressBar::hidden(),
enabled: false,
};
}
let bar = ProgressBar::new(total_bytes);
bar.set_style(
ProgressStyle::with_template(
"[{bar:40.cyan/blue}] {percent}% {bytes}/{total_bytes} {bytes_per_sec} ETA {eta}",
)
.unwrap()
.progress_chars("=>-"),
);
Self { bar, enabled: true }
}
pub fn without_size(enabled: bool) -> Self {
if !enabled {
return Self {
bar: ProgressBar::hidden(),
enabled: false,
};
}
let bar = ProgressBar::new_spinner();
bar.set_style(
ProgressStyle::with_template("{spinner:.green} {bytes} {bytes_per_sec}").unwrap(),
);
Self { bar, enabled: true }
}
pub fn advance(&self, bytes: u64) {
self.bar.inc(bytes);
}
pub fn finish(&self) {
if self.enabled {
self.bar.finish_and_clear();
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn with_size_disabled_creates_hidden_bar() {
let p = TransferProgress::with_size(1024, false);
assert!(!p.enabled);
assert!(p.bar.is_hidden());
}
#[test]
fn with_size_enabled_creates_bar_with_length() {
let p = TransferProgress::with_size(1024, true);
assert!(p.enabled);
assert_eq!(p.bar.length(), Some(1024));
}
#[test]
fn without_size_disabled_creates_hidden_bar() {
let p = TransferProgress::without_size(false);
assert!(!p.enabled);
assert!(p.bar.is_hidden());
}
#[test]
fn without_size_enabled_creates_spinner_without_length() {
let p = TransferProgress::without_size(true);
assert!(p.enabled);
assert_eq!(p.bar.length(), None);
}
#[test]
fn advance_increments_position() {
let p = TransferProgress::with_size(1000, true);
p.advance(250);
p.advance(100);
assert_eq!(p.bar.position(), 350);
}
#[test]
fn finish_is_safe_on_disabled_bar() {
let p = TransferProgress::with_size(1024, false);
p.finish();
}
#[test]
fn finish_is_safe_on_enabled_bar() {
let p = TransferProgress::with_size(1024, true);
p.finish();
}
}