workflow_utils/
format.rs

1use separator::{separated_float, separated_int, separated_uint_with_output, Separatable};
2
3/// Display KB or KiB if `short` is false, otherwise if `short` is true
4/// and the value is greater than 1MB or 1MiB, display units using [`as_data_size()`].
5pub fn as_kb(bytes: f64, si: bool, short: bool) -> String {
6    let unit = if si { 1000_f64 } else { 1024_f64 };
7    if short && bytes > unit.powi(2) {
8        as_data_size(bytes, si)
9    } else {
10        let suffix = if si { " KB" } else { " KiB" };
11        let kb = bytes / unit; //(( * 100.) as u64) as f64 / 100.;
12        format_with_precision(kb) + suffix
13    }
14}
15
16/// Display MB or MiB if `short` is false, otherwise if `short` is true
17/// and the value is greater than 1GB or 1GiB, display units using [`as_data_size()`].
18pub fn as_mb(bytes: f64, si: bool, short: bool) -> String {
19    let unit = if si { 1000_f64 } else { 1024_f64 };
20    if short && bytes > unit.powi(3) {
21        as_data_size(bytes, si)
22    } else {
23        let suffix = if si { " MB" } else { " MiB" };
24        let mb = bytes / unit.powi(2); //(( * 100.) as u64) as f64 / 100.;
25        format_with_precision(mb) + suffix
26    }
27}
28
29/// Display GB or GiB if `short` is false, otherwise if `short` is true
30/// and the value is greater than 1TB or 1TiB, display units using [`as_data_size()`].
31pub fn as_gb(bytes: f64, si: bool, short: bool) -> String {
32    let unit = if si { 1000_f64 } else { 1024_f64 };
33    if short && bytes > unit.powi(4) {
34        as_data_size(bytes, si)
35    } else {
36        let suffix = if si { " GB" } else { " GiB" };
37        let gb = bytes / unit.powi(3); //(( * 100.) as u64) as f64 / 100.;
38        format_with_precision(gb) + suffix
39    }
40}
41
42/// Display units dynamically formatted based on the size of the value.
43pub fn as_data_size(bytes: f64, si: bool) -> String {
44    let unit = if si { 1000_f64 } else { 1024_f64 };
45    let mut size = bytes;
46    let mut unit_str = " B";
47
48    if size >= unit.powi(4) {
49        size /= unit.powi(4);
50        unit_str = " TB";
51    } else if size >= unit.powi(3) {
52        size /= unit.powi(3);
53        unit_str = " GB";
54    } else if size >= unit.powi(2) {
55        size /= unit.powi(2);
56        unit_str = " MB";
57    } else if size >= unit {
58        size /= unit;
59        unit_str = " KB";
60    }
61
62    format_with_precision(size) + unit_str
63}
64
65/// Format supplied value as a float with 2 decimal places.
66pub fn format_as_float(f: f64, short: bool) -> String {
67    if short {
68        if f < 1000.0 {
69            format_with_precision(f)
70        } else if f < 1000000.0 {
71            format_with_precision(f / 1000.0) + " K"
72        } else if f < 1000000000.0 {
73            format_with_precision(f / 1000000.0) + " M"
74        } else if f < 1000000000000.0 {
75            format_with_precision(f / 1000000000.0) + " G"
76        } else if f < 1000000000000000.0 {
77            format_with_precision(f / 1000000000000.0) + " T"
78        } else if f < 1000000000000000000.0 {
79            format_with_precision(f / 1000000000000000.0) + " P"
80        } else {
81            format_with_precision(f / 1000000000000000000.0) + " E"
82        }
83    } else {
84        f.separated_string()
85    }
86}
87
88/// Format supplied value as a float with 2 decimal places.
89fn format_with_precision(f: f64) -> String {
90    if f.fract() < 0.01 {
91        separated_float!(format!("{}", f.trunc()))
92    } else {
93        separated_float!(format!("{:.2}", f))
94    }
95}