#[cfg(target_os = "linux")]
pub fn is_wsl() -> bool {
std::fs::read_to_string("/proc/version")
.map(|v| v.to_lowercase().contains("microsoft"))
.unwrap_or(false)
}
#[cfg(not(target_os = "linux"))]
pub const fn is_wsl() -> bool {
false
}
#[cfg(target_os = "macos")]
pub const fn os_name() -> &'static str {
"macos"
}
#[cfg(target_os = "linux")]
pub fn os_name() -> &'static str {
if is_wsl() { "wsl2" } else { "linux" }
}
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
pub fn os_name() -> &'static str {
"unknown"
}
#[cfg(target_os = "macos")]
pub fn total_memory_mb() -> u64 {
std::process::Command::new("sysctl")
.args(["-n", "hw.memsize"])
.output()
.ok()
.and_then(|output| {
String::from_utf8_lossy(&output.stdout)
.trim()
.parse::<u64>()
.ok()
})
.map_or(0, |bytes| bytes / (1024 * 1024))
}
#[cfg(target_os = "linux")]
pub fn total_memory_mb() -> u64 {
std::fs::read_to_string("/proc/meminfo")
.ok()
.and_then(|content| parse_meminfo_total_kb(&content))
.map_or(0, |kb| kb / 1024)
}
#[cfg(target_os = "linux")]
fn parse_meminfo_total_kb(content: &str) -> Option<u64> {
content.lines().find_map(|line| {
line.strip_prefix("MemTotal:")
.and_then(|rest| rest.split_whitespace().next())
.and_then(|value| value.parse::<u64>().ok())
})
}
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
pub const fn total_memory_mb() -> u64 {
0
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_os_name_is_known() {
let name = os_name();
assert!(
["macos", "linux", "wsl2", "unknown"].contains(&name),
"Unexpected OS name: {name}"
);
}
#[test]
fn test_is_wsl_returns_bool() {
let result = is_wsl();
assert!(!result || cfg!(target_os = "linux"));
}
#[cfg(target_os = "macos")]
#[test]
fn test_os_name_macos() {
assert_eq!(os_name(), "macos");
}
#[test]
fn test_total_memory_mb_is_sane() {
let mb = total_memory_mb();
#[cfg(any(target_os = "macos", target_os = "linux"))]
assert!(mb > 0);
#[cfg(not(any(target_os = "macos", target_os = "linux")))]
assert_eq!(mb, 0);
}
#[cfg(target_os = "linux")]
#[test]
fn test_parse_meminfo_total_kb() {
let content = "MemTotal: 16384000 kB\nMemFree: 4096000 kB\n";
assert_eq!(parse_meminfo_total_kb(content), Some(16_384_000));
}
#[cfg(target_os = "linux")]
#[test]
fn test_parse_meminfo_total_kb_missing() {
let content = "MemFree: 4096000 kB\n";
assert_eq!(parse_meminfo_total_kb(content), None);
}
}