1use crate::output::OutputConfig;
2use indicatif::{ProgressBar, ProgressStyle};
3use std::time::Duration;
4
5pub struct ProgressReporter {
7 bar: Option<ProgressBar>,
8}
9
10impl ProgressReporter {
11 pub fn new(config: &OutputConfig) -> Self {
12 let bar = if config.interactive {
13 Some(Self::create_progress_bar(config.use_colors))
14 } else {
15 None
16 };
17
18 Self { bar }
19 }
20
21 pub fn start_conversion(&self) {
23 if let Some(ref bar) = self.bar {
24 bar.set_message("Initializing conversion...");
25 bar.set_position(0);
26 }
27 }
28
29 pub fn reading_file(&self, filename: &str) {
31 if let Some(ref bar) = self.bar {
32 bar.set_message(format!("Reading PFX file: {}", filename));
33 bar.set_position(1);
34 }
35 }
36
37 pub fn parsing(&self) {
39 if let Some(ref bar) = self.bar {
40 bar.set_message("Parsing PFX structure...");
41 bar.set_position(2);
42 }
43 }
44
45 pub fn extracting_key(&self) {
47 if let Some(ref bar) = self.bar {
48 bar.set_message("Extracting private key...");
49 bar.set_position(3);
50 }
51 }
52
53 pub fn extracting_cert(&self) {
55 if let Some(ref bar) = self.bar {
56 bar.set_message("Extracting certificate...");
57 bar.set_position(4);
58 }
59 }
60
61 pub fn extracting_chain(&self, count: usize) {
63 if let Some(ref bar) = self.bar {
64 bar.set_message(format!("Extracting certificate chain ({} certs)...", count));
65 bar.set_position(5);
66 }
67 }
68
69 pub fn writing_files(&self) {
71 if let Some(ref bar) = self.bar {
72 bar.set_message("Writing PEM files...");
73 bar.set_position(6);
74 }
75 }
76
77 pub fn complete(&self) {
79 if let Some(ref bar) = self.bar {
80 bar.set_message("Conversion completed!");
81 bar.set_position(7);
82 bar.finish();
83 }
84 }
85
86 pub fn error(&self, message: &str) {
88 if let Some(ref bar) = self.bar {
89 bar.abandon_with_message(format!("Error: {}", message));
90 }
91 }
92
93 fn create_progress_bar(use_colors: bool) -> ProgressBar {
95 let bar = ProgressBar::new(7);
96
97 if use_colors {
98 bar.set_style(
99 ProgressStyle::default_bar()
100 .template("{spinner:.green} [{elapsed_precise}] [{bar:40.cyan/blue}] {pos}/{len} {msg}")
101 .unwrap()
102 .progress_chars("█▉▊▋▌▍▎▏ "),
103 );
104 } else {
105 bar.set_style(
106 ProgressStyle::default_bar()
107 .template("{spinner} [{elapsed_precise}] [{bar:40}] {pos}/{len} {msg}")
108 .unwrap()
109 .progress_chars("#>-"),
110 );
111 }
112
113 bar.enable_steady_tick(Duration::from_millis(100));
114 bar
115 }
116}
117
118impl Drop for ProgressReporter {
119 fn drop(&mut self) {
120 if let Some(ref bar) = self.bar {
121 bar.finish_and_clear();
122 }
123 }
124}