1use std::{io::{Write, stdout, stderr, Result}, time::Instant};
2
3#[derive(Default, Copy, Clone)]
5pub enum Stream {
6 #[default]
7 Stderr,
8 Stdout,
9}
10impl Stream {
11 fn match_target(&self) -> Box<dyn Write> {
13 match self {
14 Self::Stderr => Box::new(stderr()),
15 Self::Stdout => Box::new(stdout())
16 }
17 }
18
19 fn print_message(
21 writer: &mut Box<dyn Write>,
22 frame: &str,
23 message: &str) -> Result<()>
24 {
25 write!(writer, "\r{} {}", frame, message)?;
26 writer.flush()
27 }
28
29 fn print_message_with_duration(
31 writer: &mut Box<dyn Write>,
32 frame: &str,
33 message: &str,
34 start_time: Instant,
35 stop_time: Option<Instant>) -> Result<()>
36 {
37 let now = stop_time.unwrap_or_else(Instant::now);
38 let duration = now.duration_since(start_time).as_secs_f64();
39 write!(writer, "\r{}{:>10.3} s\t{}", frame, duration, message)?;
40 writer.flush()
41 }
42
43 pub fn write(
45 &self,
46 frame: &str,
47 message: &str,
48 start_time: Option<Instant>,
49 stop_time: Option<Instant>) -> Result<()>
50 {
51 let mut writer = self.match_target();
52 match start_time {
53 None => Self::print_message(
54 &mut writer, frame, message)?,
55 Some(start_time) => Self::print_message_with_duration(
56 &mut writer, frame, message, start_time, stop_time)?
57 };
58 Ok(())
59 }
60
61 pub fn stop(
63 &self,
64 message: Option<&str>,
65 symbol: Option<&str>) -> Result<()>
66 {
67 let mut writer = self.match_target();
68 match (message, symbol) {
69 (Some(m), Some(s)) => writeln!(writer, "\x1b[2K\r{} {}", s, m),
71
72 (Some(m), None) => writeln!(writer, "\x1b[2K\r{}", m),
74
75 _ => writeln!(writer)
77 }?;
78 writer.flush()
79 }
80}