ecad_processor/utils/
progress.rs1use indicatif::{ProgressBar, ProgressStyle};
2use std::time::Duration;
3
4pub struct ProgressReporter {
5 progress_bar: Option<ProgressBar>,
6 silent: bool,
7}
8
9impl ProgressReporter {
10 pub fn new(total: u64, message: &str, silent: bool) -> Self {
11 if silent {
12 Self {
13 progress_bar: None,
14 silent: true,
15 }
16 } else {
17 let pb = ProgressBar::new(total);
18 pb.set_style(
19 ProgressStyle::default_bar()
20 .template("{msg}\n{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} ({eta})")
21 .unwrap()
22 .progress_chars("#>-"),
23 );
24 pb.set_message(message.to_string());
25 pb.enable_steady_tick(Duration::from_millis(100));
26
27 Self {
28 progress_bar: Some(pb),
29 silent: false,
30 }
31 }
32 }
33
34 pub fn new_spinner(message: &str, silent: bool) -> Self {
35 if silent {
36 Self {
37 progress_bar: None,
38 silent: true,
39 }
40 } else {
41 let pb = ProgressBar::new_spinner();
42 pb.set_style(
43 ProgressStyle::default_spinner()
44 .template("{spinner:.green} {msg}")
45 .unwrap(),
46 );
47 pb.set_message(message.to_string());
48 pb.enable_steady_tick(Duration::from_millis(100));
49
50 Self {
51 progress_bar: Some(pb),
52 silent: false,
53 }
54 }
55 }
56
57 pub fn update(&self, current: u64) {
58 if let Some(ref pb) = self.progress_bar {
59 pb.set_position(current);
60 }
61 }
62
63 pub fn increment(&self, delta: u64) {
64 if let Some(ref pb) = self.progress_bar {
65 pb.inc(delta);
66 }
67 }
68
69 pub fn set_message(&self, message: &str) {
70 if let Some(ref pb) = self.progress_bar {
71 pb.set_message(message.to_string());
72 }
73 }
74
75 pub fn finish_with_message(&self, message: &str) {
76 if let Some(ref pb) = self.progress_bar {
77 pb.finish_with_message(message.to_string());
78 }
79 }
80
81 pub fn finish(&self) {
82 if let Some(ref pb) = self.progress_bar {
83 pb.finish();
84 }
85 }
86
87 pub fn println(&self, message: &str) {
88 if !self.silent {
89 if let Some(ref pb) = self.progress_bar {
90 pb.println(message);
91 } else {
92 println!("{}", message);
93 }
94 }
95 }
96}
97
98impl Drop for ProgressReporter {
99 fn drop(&mut self) {
100 if let Some(ref pb) = self.progress_bar {
101 pb.finish();
102 }
103 }
104}
105
106pub struct MultiProgressReporter {
108 bars: Vec<ProgressBar>,
109 silent: bool,
110}
111
112impl MultiProgressReporter {
113 pub fn new(tasks: Vec<(&str, u64)>, silent: bool) -> Self {
114 if silent {
115 Self {
116 bars: vec![],
117 silent: true,
118 }
119 } else {
120 let bars: Vec<ProgressBar> = tasks
121 .into_iter()
122 .map(|(name, total)| {
123 let pb = ProgressBar::new(total);
124 pb.set_style(
125 ProgressStyle::default_bar()
126 .template("{prefix:>12} [{bar:40.cyan/blue}] {pos}/{len}")
127 .unwrap()
128 .progress_chars("#>-"),
129 );
130 pb.set_prefix(name.to_string());
131 pb
132 })
133 .collect();
134
135 Self {
136 bars,
137 silent: false,
138 }
139 }
140 }
141
142 pub fn get_bar(&self, index: usize) -> Option<&ProgressBar> {
143 if self.silent {
144 None
145 } else {
146 self.bars.get(index)
147 }
148 }
149
150 pub fn finish_all(&self) {
151 for bar in &self.bars {
152 bar.finish();
153 }
154 }
155}