1use crate::formatting::Format;
2
3#[derive(Clone, Copy, clap::ValueEnum)]
4pub enum Unit {
5 #[value(name = "ns")]
7 Nanoseconds,
8 #[value(name = "us")]
9 Microseconds,
10 #[value(name = "ms")]
11 Milliseconds,
12 #[value(name = "s")]
13 Seconds,
14
15 #[value(name = "B")]
17 Bytes,
18 #[value(name = "KB")]
19 Kilobytes,
20 #[value(name = "MB")]
21 Megabytes,
22 #[value(name = "GB")]
23 Gigabytes,
24 #[value(name = "TB")]
25 Terabytes,
26 #[value(name = "PB")]
27 Petabytes,
28
29 #[value(name = "KiB")]
31 Kibibytes,
32 #[value(name = "MiB")]
33 Mebibytes,
34 #[value(name = "GiB")]
35 Gibibytes,
36 #[value(name = "TiB")]
37 Tebibytes,
38 #[value(name = "PiB")]
39 Pebibytes,
40}
41
42impl Unit {
43 pub fn scale(&self) -> f64 {
45 match self {
46 Self::Nanoseconds => 1.0,
48 Self::Microseconds => 1e3,
49 Self::Milliseconds => 1e6,
50 Self::Seconds => 1e9,
51
52 Self::Bytes => 1.0,
54 Self::Kilobytes => 1e3,
55 Self::Megabytes => 1e6,
56 Self::Gigabytes => 1e9,
57 Self::Terabytes => 1e12,
58 Self::Petabytes => 1e15,
59 Self::Kibibytes => 1024.0,
60 Self::Mebibytes => 1024.0_f64.powi(2),
61 Self::Gibibytes => 1024.0_f64.powi(3),
62 Self::Tebibytes => 1024.0_f64.powi(4),
63 Self::Pebibytes => 1024.0_f64.powi(5),
64 }
65 }
66
67 pub fn default_format(&self) -> Format {
69 match self {
70 Self::Nanoseconds | Self::Microseconds | Self::Milliseconds | Self::Seconds => {
71 Format::Time
72 }
73 _ => Format::Bytes,
74 }
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81
82 #[test]
83 fn test_time_unit_scales() {
84 assert_eq!(Unit::Nanoseconds.scale(), 1.0);
85 assert_eq!(Unit::Microseconds.scale(), 1e3);
86 assert_eq!(Unit::Milliseconds.scale(), 1e6);
87 assert_eq!(Unit::Seconds.scale(), 1e9);
88 }
89
90 #[test]
91 fn test_decimal_byte_unit_scales() {
92 assert_eq!(Unit::Bytes.scale(), 1.0);
93 assert_eq!(Unit::Kilobytes.scale(), 1e3);
94 assert_eq!(Unit::Megabytes.scale(), 1e6);
95 assert_eq!(Unit::Gigabytes.scale(), 1e9);
96 assert_eq!(Unit::Terabytes.scale(), 1e12);
97 assert_eq!(Unit::Petabytes.scale(), 1e15);
98 }
99
100 #[test]
101 fn test_binary_byte_unit_scales() {
102 assert_eq!(Unit::Kibibytes.scale(), 1024.0);
103 assert_eq!(Unit::Mebibytes.scale(), 1024.0_f64.powi(2));
104 assert_eq!(Unit::Gibibytes.scale(), 1024.0_f64.powi(3));
105 assert_eq!(Unit::Tebibytes.scale(), 1024.0_f64.powi(4));
106 assert_eq!(Unit::Pebibytes.scale(), 1024.0_f64.powi(5));
107 }
108
109 #[test]
110 fn test_time_unit_default_format() {
111 assert!(matches!(Unit::Nanoseconds.default_format(), Format::Time));
112 assert!(matches!(Unit::Microseconds.default_format(), Format::Time));
113 assert!(matches!(Unit::Milliseconds.default_format(), Format::Time));
114 assert!(matches!(Unit::Seconds.default_format(), Format::Time));
115 }
116
117 #[test]
118 fn test_byte_unit_default_format() {
119 assert!(matches!(Unit::Bytes.default_format(), Format::Bytes));
120 assert!(matches!(Unit::Kilobytes.default_format(), Format::Bytes));
121 assert!(matches!(Unit::Megabytes.default_format(), Format::Bytes));
122 assert!(matches!(Unit::Kibibytes.default_format(), Format::Bytes));
123 assert!(matches!(Unit::Mebibytes.default_format(), Format::Bytes));
124 }
125
126 #[test]
127 fn test_conversion_examples() {
128 assert_eq!(5.0 * Unit::Microseconds.scale(), 5000.0);
130
131 assert_eq!(2.0 * Unit::Megabytes.scale(), 2_000_000.0);
133
134 assert_eq!(3.0 * Unit::Mebibytes.scale(), 3_145_728.0);
136 }
137
138 #[test]
139 fn test_decimal_vs_binary_difference() {
140 let mb = Unit::Megabytes.scale();
143 let mib = Unit::Mebibytes.scale();
144
145 assert_eq!(mb, 1e6);
146 assert_eq!(mib, 1024.0 * 1024.0);
147 assert!(mib > mb);
148 assert!((mib - mb).abs() > 48_000.0); }
150}