1use std::time::Instant;
2
3pub const RESET: &str = "\x1b[0m";
5pub const RED: &str = "\x1b[31m";
7pub const GREY: &str = "\x1b[90m";
9
10static mut START: Option<Instant> = None;
11
12pub fn d_prn<S: ToString>(s: S) {
13 let start = d_start();
14 let t = Instant::now() - start;
15
16 eprintln!("{} {}", internal::disp_time(&t), s.to_string());
17}
18
19pub fn d_start() -> Instant {
20 match unsafe { START } {
21 Some(t) => t,
22 None => {
23 eprintln!();
24 eprintln!("{} START", internal::fo(" s", " ms", " µs"));
25 let now = Instant::now();
26 unsafe { START = Some(now) };
27 now
28 }
29 }
30}
31
32pub fn d_end() {
33 d_prn("END");
34 eprintln!();
35}
36
37#[macro_export]
38macro_rules! d {
39 { @ $expr:expr => $val:ident ( $($format_args:tt)+ ) } => {
43 match $expr {
45 $val => {
46 let args = format!($($format_args)+);
47 d!(@raw args);
48 $val
49 }
50 }
51 };
52 { @raw $expr:expr } => { {
53 let thread = format!("[{}]", std::thread::current().name().unwrap_or("???"));
54 let pos = format!("{}:{}", file!(), line!());
55 let val = $expr;
56 $crate::d_prn(format!("{:6} {} {}{}{}", thread, &val, $crate::GREY, pos, $crate::RESET));
57 val
58 } };
59 { @ $($tt:tt)* } => {
60 d!(@raw format!($($tt)*))
61 };
62
63 {} => { d! { @() => val ("") } };
64
65 { #? $val:expr } => { d! { @ $val => val ("{} = {:#?}", stringify!($val), val) } };
69 { ? $val:expr } => { d! { @ $val => val ("{} = {:?}", stringify!($val), val) } };
70 { $val:expr } => { d! { @ $val => val ("{}", val) } };
71}
72
73mod internal {
74 use std::time::Duration;
75
76 #[rustfmt::skip]
77 pub fn disp_time(t: &Duration) -> String {
78 let n = t.as_micros();
79
80 let s2 = String::from(" ");
81 let s3 = String::from(" ");
82
83 match (n / 1000_000, n / 1000 % 1000, n % 1000) {
84 (0, 0, 0) => fo(s2, s3, " 0"),
85 (0, 0, us) => fo(s2, s3, format!( "{:3}", us)),
86 (0, ms, us) => fo(s2, format!( "{:3}", ms), format!("{:03}", us)),
87 (s, ms, us) => fo(format!("{:2}", s), format!("{:03}", ms), format!("{:03}", us)),
88 }
89 }
90
91 pub fn fo(s: impl Into<String>, ms: impl Into<String>, us: impl Into<String>) -> String {
92 const S: &str = super::RED;
93 const MS: &str = super::RESET;
94 const US: &str = super::GREY;
95 const RST: &str = super::RESET;
96
97 let (s, ms, us) = (s.into(), ms.into(), us.into());
98
99 format!("{s}{}{rst}{ms}{}{rst} {us}{}{rst}", s, ms, us, s = S, ms = MS, us = US, rst = RST)
100 }
101}