vanity_ssh_rs/monitor/
progress.rs1use indicatif::{ProgressBar, ProgressStyle};
2use num_format::{Locale, ToFormattedString};
3use std::sync::mpsc::Receiver;
4use std::time::{Duration, Instant};
5
6use crate::core::pattern::Pattern;
7use crate::core::result::SearchResult;
8use crate::worker::message::WorkerMessage;
9
10pub fn monitor_progress(
11 rx: Receiver<WorkerMessage>,
12 start: Instant,
13 pattern: &Pattern,
14) -> SearchResult {
15 let mut total_attempts = 0;
16 let mut found_key_pair = None;
17
18 let pb = ProgressBar::new_spinner();
19 pb.set_style(
20 ProgressStyle::default_spinner()
21 .template("{spinner:.green} [{elapsed_precise}]\n{msg}")
22 .unwrap(),
23 );
24 pb.enable_steady_tick(Duration::from_millis(100));
25
26 while found_key_pair.is_none() {
27 if let Ok(msg) = rx.recv() {
28 total_attempts += msg.attempts;
29 if let Some(key) = msg.found_key {
30 found_key_pair = Some(key);
31 } else {
32 let duration = start.elapsed();
33 let rate = (total_attempts as f64 / duration.as_secs_f64()).round() as u64;
34
35 let mut progress_msg = format!(
36 "Attempts: {} ({} keys/sec)",
37 total_attempts.to_formatted_string(&Locale::en),
38 rate.to_formatted_string(&Locale::en)
39 );
40
41 if let Some(prob) = pattern.probability() {
42 let expected_attempts = (1.0 / prob) as u64;
43 let est_time = pattern
44 .estimate_time(rate as f64)
45 .unwrap_or_default()
46 .split_whitespace()
47 .take(2)
48 .collect::<Vec<_>>()
49 .join(" ");
50
51 progress_msg = format!(
52 "{}\nProbability: 1 in {}\nEst. time: {}",
53 progress_msg,
54 expected_attempts.to_formatted_string(&Locale::en),
55 est_time
56 );
57 }
58
59 pb.set_message(progress_msg);
60 }
61 }
62 }
63
64 pb.finish_and_clear();
65
66 SearchResult {
67 key_pair: found_key_pair.unwrap(),
68 total_attempts,
69 duration: start.elapsed(),
70 }
71}