use unit_prefix::NumberPrefix;
#[derive(Copy, Clone, PartialEq)]
pub enum SizeFormat {
Bytes,
Binary, Decimal, }
fn format_prefixed(prefixed: &NumberPrefix<f64>) -> String {
match prefixed {
NumberPrefix::Standalone(bytes) => bytes.to_string(),
NumberPrefix::Prefixed(prefix, bytes) => {
let prefix_str = prefix.symbol().trim_end_matches('i');
if (10.0 * bytes).ceil() >= 100.0 {
format!("{:.0}{prefix_str}", bytes.ceil())
} else {
format!("{:.1}{prefix_str}", (10.0 * bytes).ceil() / 10.0)
}
}
}
}
pub fn human_readable(size: u64, sfmt: SizeFormat) -> String {
match sfmt {
SizeFormat::Binary => format_prefixed(&NumberPrefix::binary(size as f64)),
SizeFormat::Decimal => format_prefixed(&NumberPrefix::decimal(size as f64)),
SizeFormat::Bytes => size.to_string(),
}
}
#[cfg(test)]
#[test]
fn test_human_readable() {
let test_cases = [
(133_456_345, SizeFormat::Binary, "128M"),
(12 * 1024 * 1024, SizeFormat::Binary, "12M"),
(8500, SizeFormat::Binary, "8.4K"),
];
for &(size, sfmt, expected_str) in &test_cases {
assert_eq!(human_readable(size, sfmt), expected_str);
}
}