1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
const KUNIT: usize = 1024; // a kunit of memory is 1024 things (bytes, kilobytes, ...)
const PREFIXES: &str = "KMGTPE"; // prefixes for memory quantities KiB, MiB, GiB, ...
// Create a human-readable string representation of the memory size
pub fn memory_size(total: usize) -> String {
if total < KUNIT {
format!("{total} B")
} else {
// Compute the index in the prefixes string above
let mut idx = 0;
let mut d = KUNIT;
let mut n = total / KUNIT;
while n >= KUNIT {
d *= KUNIT;
idx += 1;
n /= KUNIT;
}
let value = total as f64 / d as f64;
let prefix =
////////////////////////////////////////////////////////////////////////
// Famous last words: 1023 exabytes ought to be enough for anybody //
// //
// Corollary: //
// unwrap() below shouldn't fail //
// The maximum representation for usize corresponds to 16 exabytes //
// anyway //
////////////////////////////////////////////////////////////////////////
PREFIXES.chars().nth(idx).unwrap();
format!("{:.1} {}iB", value, prefix)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_memory_size() {
assert_eq!(memory_size(1023_usize), "1023 B");
assert_eq!(memory_size(1024_usize), "1.0 KiB");
assert_eq!(memory_size(1024 * 1024_usize), "1.0 MiB");
assert_eq!(memory_size(2100 * 1024 * 1024_usize), "2.1 GiB");
assert_eq!(memory_size(std::usize::MAX), "16.0 EiB");
}
}