fast_rich/
filesize.rs

1//! Filesize formatting utilities.
2
3const SUFFIXES: [&str; 9] = ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
4const BINARY_SUFFIXES: [&str; 9] = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
5
6/// Convert a size in bytes to a human readable string using decimal suffixes (kB, MB).
7pub fn decimal(size: u64) -> String {
8    format_size(size, 1000.0, &SUFFIXES)
9}
10
11/// Convert a size in bytes to a human readable string using binary suffixes (KiB, MiB).
12pub fn binary(size: u64) -> String {
13    format_size(size, 1024.0, &BINARY_SUFFIXES)
14}
15
16fn format_size(size: u64, divisor: f64, suffixes: &[&str]) -> String {
17    if size == 0 {
18        return format!("0 {}", suffixes[0]);
19    }
20
21    let size_f = size as f64;
22    let i = (size_f.log(divisor).floor() as usize).min(suffixes.len() - 1);
23
24    if i == 0 {
25        format!("{} {}", size, suffixes[0])
26    } else {
27        let val = size_f / divisor.powi(i as i32);
28        format!("{:.1} {}", val, suffixes[i])
29    }
30}
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35
36    #[test]
37    fn test_decimal() {
38        assert_eq!(decimal(0), "0 B");
39        assert_eq!(decimal(500), "500 B");
40        assert_eq!(decimal(1000), "1.0 kB");
41        assert_eq!(decimal(1500), "1.5 kB");
42        assert_eq!(decimal(1_000_000), "1.0 MB");
43    }
44
45    #[test]
46    fn test_binary() {
47        assert_eq!(binary(0), "0 B");
48        assert_eq!(binary(1024), "1.0 KiB");
49        assert_eq!(binary(1536), "1.5 KiB");
50        assert_eq!(binary(1_048_576), "1.0 MiB");
51    }
52}