leenfetch_core/modules/linux/info/
memory.rs

1use std::fs;
2
3use crate::modules::enums::MemoryUnit;
4
5pub fn get_memory(memory_percent: bool, memory_unit: MemoryUnit) -> Option<String> {
6    let contents = fs::read_to_string("/proc/meminfo").ok()?;
7
8    let mut mem_total_kb = 0;
9    let mut mem_available_kb = None;
10    let mut shmem = 0;
11    let mut memfree = 0;
12    let mut buffers = 0;
13    let mut cached = 0;
14    let mut sreclaimable = 0;
15
16    for line in contents.lines() {
17        let mut parts = line.split_whitespace();
18        match parts.next()? {
19            "MemTotal:" => mem_total_kb = parts.next()?.parse::<u64>().ok()?,
20            "MemAvailable:" => mem_available_kb = parts.next()?.parse::<u64>().ok(),
21            "Shmem:" => shmem = parts.next()?.parse::<u64>().ok()?,
22            "MemFree:" => memfree = parts.next()?.parse::<u64>().ok()?,
23            "Buffers:" => buffers = parts.next()?.parse::<u64>().ok()?,
24            "Cached:" => cached = parts.next()?.parse::<u64>().ok()?,
25            "SReclaimable:" => sreclaimable = parts.next()?.parse::<u64>().ok()?,
26            _ => {}
27        }
28    }
29
30    let used_kb = if let Some(avail) = mem_available_kb {
31        mem_total_kb.saturating_sub(avail)
32    } else {
33        mem_total_kb + shmem - memfree - buffers - cached - sreclaimable
34    };
35
36    let (used, total, unit_str) = match memory_unit {
37        MemoryUnit::GiB => (
38            used_kb as f64 / 1024.0 / 1024.0,
39            mem_total_kb as f64 / 1024.0 / 1024.0,
40            "GiB",
41        ),
42        MemoryUnit::KiB => (used_kb as f64, mem_total_kb as f64, "KiB"),
43        MemoryUnit::MiB => (used_kb as f64 / 1024.0, mem_total_kb as f64 / 1024.0, "MiB"),
44    };
45
46    let percent = if memory_percent {
47        format!(" ({:.0}%)", used / total * 100.0)
48    } else {
49        "".to_string()
50    };
51
52    Some(format!(
53        "{:.1}{} / {:.1}{}{}",
54        used, unit_str, total, unit_str, percent
55    ))
56}
57
58#[cfg(test)]
59mod tests {
60    use super::*;
61
62    #[test]
63    fn test_memory_output_mib() {
64        let result = get_memory(false, MemoryUnit::MiB);
65        assert!(result.is_some());
66        assert!(result.unwrap().contains("MiB"));
67    }
68
69    #[test]
70    fn test_memory_output_gib_with_percent() {
71        let result = get_memory(true, MemoryUnit::GiB);
72        let output = result.unwrap();
73        assert!(output.contains("GiB"));
74        assert!(output.contains('%'));
75    }
76
77    #[test]
78    fn test_memory_output_kib() {
79        let result = get_memory(false, MemoryUnit::KiB);
80        assert!(result.unwrap().contains("KiB"));
81    }
82}