Skip to main content

ringkernel_core/resource/
system.rs

1//! System memory utilities.
2
3/// Gets available system memory in bytes.
4///
5/// Returns None if unable to determine.
6#[must_use]
7pub fn get_available_memory() -> Option<u64> {
8    #[cfg(target_os = "linux")]
9    {
10        use std::fs;
11        if let Ok(meminfo) = fs::read_to_string("/proc/meminfo") {
12            for line in meminfo.lines() {
13                if line.starts_with("MemAvailable:") {
14                    let parts: Vec<&str> = line.split_whitespace().collect();
15                    if parts.len() >= 2 {
16                        if let Ok(kb) = parts[1].parse::<u64>() {
17                            return Some(kb * 1024);
18                        }
19                    }
20                }
21            }
22        }
23        None
24    }
25
26    #[cfg(target_os = "macos")]
27    {
28        // On macOS, we could use sysctl, but for simplicity return None
29        // and let callers use conservative defaults
30        None
31    }
32
33    #[cfg(target_os = "windows")]
34    {
35        // On Windows, we could use GlobalMemoryStatusEx, but for simplicity
36        // return None and let callers use conservative defaults
37        None
38    }
39
40    #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
41    {
42        None
43    }
44}
45
46/// Gets total system memory in bytes.
47///
48/// Returns None if unable to determine.
49#[must_use]
50pub fn get_total_memory() -> Option<u64> {
51    #[cfg(target_os = "linux")]
52    {
53        use std::fs;
54        if let Ok(meminfo) = fs::read_to_string("/proc/meminfo") {
55            for line in meminfo.lines() {
56                if line.starts_with("MemTotal:") {
57                    let parts: Vec<&str> = line.split_whitespace().collect();
58                    if parts.len() >= 2 {
59                        if let Ok(kb) = parts[1].parse::<u64>() {
60                            return Some(kb * 1024);
61                        }
62                    }
63                }
64            }
65        }
66        None
67    }
68
69    #[cfg(target_os = "macos")]
70    {
71        None
72    }
73
74    #[cfg(target_os = "windows")]
75    {
76        None
77    }
78
79    #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))]
80    {
81        None
82    }
83}
84
85/// Gets system memory utilization (0.0-1.0).
86///
87/// Returns None if unable to determine.
88#[must_use]
89#[allow(dead_code)]
90pub fn get_memory_utilization() -> Option<f64> {
91    let total = get_total_memory()?;
92    let available = get_available_memory()?;
93
94    if total == 0 {
95        return None;
96    }
97
98    let used = total.saturating_sub(available);
99    Some(used as f64 / total as f64)
100}
101
102#[cfg(test)]
103mod tests {
104    use super::*;
105
106    #[test]
107    fn test_get_available_memory() {
108        // This may or may not return a value depending on platform
109        let _memory = get_available_memory();
110    }
111
112    #[test]
113    fn test_get_total_memory() {
114        let _memory = get_total_memory();
115    }
116
117    #[test]
118    fn test_get_memory_utilization() {
119        if let Some(util) = get_memory_utilization() {
120            assert!((0.0..=1.0).contains(&util));
121        }
122    }
123}