dsi_progress_logger/
utils.rs1#[derive(Debug, Copy, Clone)]
14pub enum TimeUnit {
15 NanoSeconds,
17 MicroSeconds,
19 MilliSeconds,
21 Seconds,
23 Minutes,
25 Hours,
27 Days,
29}
30
31impl TimeUnit {
32 pub const VALUES: [TimeUnit; 7] = [
34 TimeUnit::NanoSeconds,
35 TimeUnit::MicroSeconds,
36 TimeUnit::MilliSeconds,
37 TimeUnit::Seconds,
38 TimeUnit::Minutes,
39 TimeUnit::Hours,
40 TimeUnit::Days,
41 ];
42
43 pub const fn label(&self) -> &'static str {
46 match self {
47 TimeUnit::NanoSeconds => "ns",
48 TimeUnit::MicroSeconds => "μs",
49 TimeUnit::MilliSeconds => "ms",
50 TimeUnit::Seconds => "s",
51 TimeUnit::Minutes => "m",
52 TimeUnit::Hours => "h",
53 TimeUnit::Days => "d",
54 }
55 }
56
57 pub const fn as_seconds(&self) -> f64 {
59 match self {
60 TimeUnit::NanoSeconds => 1.0e-9,
61 TimeUnit::MicroSeconds => 1.0e-6,
62 TimeUnit::MilliSeconds => 1.0e-3,
63 TimeUnit::Seconds => 1.0,
64 TimeUnit::Minutes => 60.0,
65 TimeUnit::Hours => 3600.0,
66 TimeUnit::Days => 86400.0,
67 }
68 }
69
70 pub const fn nice_time_unit(seconds: f64) -> Self {
76 let mut i = TimeUnit::VALUES.len();
77 while i > 0 {
78 i -= 1;
79 if seconds >= TimeUnit::VALUES[i].as_seconds() {
80 return TimeUnit::VALUES[i];
81 }
82 }
83 TimeUnit::NanoSeconds
84 }
85
86 pub const fn nice_speed_unit(seconds: f64) -> Self {
94 let mut i = 3;
95 while i < TimeUnit::VALUES.len() {
96 if seconds <= TimeUnit::VALUES[i].as_seconds() {
97 return TimeUnit::VALUES[i];
98 }
99 i += 1;
100 }
101 TimeUnit::Days
102 }
103
104 pub fn pretty_print(milliseconds: u128) -> String {
110 let mut result = String::new();
111
112 if milliseconds < 1000 {
113 return format!("{}ms", milliseconds);
114 }
115
116 let mut seconds = milliseconds / 1000;
117
118 for unit in [TimeUnit::Days, TimeUnit::Hours, TimeUnit::Minutes] {
119 let to_seconds = unit.as_seconds() as u128;
120 if seconds >= to_seconds {
121 result.push_str(&format!("{}{} ", seconds / to_seconds, unit.label(),));
122 seconds %= to_seconds;
123 }
124 }
125
126 result.push_str(&format!("{}s", seconds));
127
128 result
129 }
130}
131
132pub const fn scale(mut val: f64) -> (f64, &'static str) {
138 const UNITS: &[&str] = &["", "k", "M", "G", "T", "P", "E", "Z", "Y"];
139 let mut i = 0;
140 while i < UNITS.len() {
141 if val < 1000.0 {
142 return (val, UNITS[i]);
143 }
144 val /= 1000.0;
145 i += 1;
146 }
147
148 (val, "Y")
149}
150
151pub fn humanize(val: f64) -> String {
154 let (val, unit) = scale(val);
155 format!("{:.2}{}", val, unit)
156}
157
158#[cfg(test)]
159mod tests {
160 use super::*;
161
162 #[test]
163 fn test_scale() {
164 assert_eq!(scale(1000.0), (1.0, "k"));
165 assert_eq!(scale(300_000.0), (300.0, "k"));
166 assert_eq!(scale(1_000_000_000.0), (1.0, "G"));
167 }
168
169 #[test]
170 fn test_humanize() {
171 assert_eq!(humanize(1000.0), "1.00k");
172 assert_eq!(humanize(12_345.0), "12.35k");
173 assert_eq!(humanize(1_234_567_890.0), "1.23G");
174 }
175
176 #[test]
177 fn test_pretty_print() {
178 assert_eq!(TimeUnit::pretty_print(500), "500ms");
179 assert_eq!(TimeUnit::pretty_print(1000), "1s");
180 assert_eq!(TimeUnit::pretty_print(1500), "1s");
181 assert_eq!(TimeUnit::pretty_print(90_061_000), "1d 1h 1m 1s");
182 }
183
184 #[test]
185 fn test_nice_units() {
186 assert_eq!(TimeUnit::nice_time_unit(0.5).label(), "ms");
187 assert_eq!(TimeUnit::nice_time_unit(100.0).label(), "m");
188 assert_eq!(TimeUnit::nice_speed_unit(0.5).label(), "s");
189 assert_eq!(TimeUnit::nice_speed_unit(100.0).label(), "h");
190 }
191}