o1vm/
utils.rs

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