liboxen/core/progress/
sync_progress.rs1use indicatif::{ProgressBar, ProgressStyle};
2use std::{
3 borrow::Cow,
4 sync::{
5 Arc,
6 atomic::{AtomicU64, Ordering},
7 },
8};
9
10pub enum SyncType {
11 Push,
12 Pull,
13}
14
15impl SyncType {
16 pub fn as_str(&self) -> &str {
17 match self {
18 SyncType::Push => "push",
19 SyncType::Pull => "pull",
20 }
21 }
22}
23
24pub struct SyncProgress {
25 sync_type: SyncType,
26 byte_counter: Arc<AtomicU64>,
27 file_counter: Arc<AtomicU64>,
28 progress_bar: ProgressBar,
29 total_files: Option<u64>,
30 total_bytes: Option<u64>,
31}
32
33impl SyncProgress {
34 pub fn new(sync_type: SyncType) -> Self {
35 let progress_bar = ProgressBar::new_spinner();
36 progress_bar.set_style(ProgressStyle::default_spinner());
37 progress_bar.enable_steady_tick(std::time::Duration::from_millis(100));
38
39 SyncProgress {
40 sync_type,
41 byte_counter: Arc::new(AtomicU64::new(0)),
42 file_counter: Arc::new(AtomicU64::new(0)),
43 progress_bar,
44 total_files: None,
45 total_bytes: None,
46 }
47 }
48
49 pub fn new_with_totals(sync_type: SyncType, total_files: u64, total_bytes: u64) -> Self {
50 let progress_bar = ProgressBar::new(total_bytes);
51 progress_bar.set_style(
52 ProgressStyle::default_bar()
53 .template(
54 "{spinner:.green} {msg} [{elapsed_precise}] [{wide_bar}] {bytes}/{total_bytes}",
55 )
56 .unwrap()
57 .progress_chars("πΎπβ"),
58 );
59
60 SyncProgress {
61 sync_type,
62 byte_counter: Arc::new(AtomicU64::new(0)),
63 file_counter: Arc::new(AtomicU64::new(0)),
64 progress_bar,
65 total_files: Some(total_files),
66 total_bytes: Some(total_bytes),
67 }
68 }
69
70 pub fn set_totals(&mut self, total_files: u64, total_bytes: u64) {
71 self.total_files = Some(total_files);
72 self.total_bytes = Some(total_bytes);
73 }
74
75 pub fn set_message(&self, message: impl Into<Cow<'static, str>>) {
76 self.progress_bar.set_message(message);
77 }
78
79 pub fn update_message(&self) {
80 let files = self.file_counter.load(Ordering::Relaxed);
81 let bytes = self.byte_counter.load(Ordering::Relaxed);
82 match (self.total_files, self.total_bytes) {
83 (Some(total_files), Some(_)) => {
84 self.progress_bar.set_message(format!(
95 "π {} ({}/{} files)",
96 self.sync_type.as_str(),
97 files,
98 total_files
99 ));
100 self.progress_bar.set_position(bytes);
101 }
102 _ => {
103 let message = format!(
104 "π {} ({} files {})",
105 self.sync_type.as_str(),
106 files,
107 bytesize::ByteSize::b(bytes)
108 );
109 self.progress_bar.set_message(message);
110 }
111 };
112 }
113
114 pub fn add_files(&self, files: u64) {
115 self.file_counter.fetch_add(files, Ordering::Relaxed);
116 self.update_message();
117 }
118
119 pub fn add_bytes(&self, bytes: u64) {
120 self.byte_counter.fetch_add(bytes, Ordering::Relaxed);
121 self.update_message();
122 }
123
124 pub fn get_num_files(&self) -> u64 {
125 self.file_counter.load(Ordering::Relaxed)
126 }
127
128 pub fn get_num_bytes(&self) -> u64 {
129 self.byte_counter.load(Ordering::Relaxed)
130 }
131
132 pub fn finish(&self) {
133 self.progress_bar.finish_and_clear();
134 }
135}