use std::path::PathBuf;
pub mod hardware;
pub mod integration;
#[derive(Debug, Clone)]
pub struct PlatformInfo {
pub os: String,
pub version: String,
pub architecture: String,
pub cpu_cores: usize,
pub total_memory: u64,
pub available_memory: u64,
}
pub fn get_platform_info() -> PlatformInfo {
let os = std::env::consts::OS.to_string();
let architecture = std::env::consts::ARCH.to_string();
let cpu_cores = num_cpus::get();
let (total_memory, available_memory) = get_memory_info();
PlatformInfo {
os: os.clone(),
version: get_os_version(),
architecture,
cpu_cores,
total_memory,
available_memory,
}
}
fn get_os_version() -> String {
#[cfg(target_os = "windows")]
{
"Windows".to_string()
}
#[cfg(target_os = "macos")]
{
use std::process::Command;
match Command::new("sw_vers").arg("-productVersion").output() {
Ok(output) => String::from_utf8_lossy(&output.stdout).trim().to_string(),
Err(_) => "macOS".to_string(),
}
}
#[cfg(target_os = "linux")]
{
use std::fs;
if let Ok(content) = fs::read_to_string("/etc/os-release") {
for line in content.lines() {
if line.starts_with("PRETTY_NAME=") {
return line
.trim_start_matches("PRETTY_NAME=")
.trim_matches('"')
.to_string();
}
}
}
"Linux".to_string()
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
"Unknown".to_string()
}
}
fn get_memory_info() -> (u64, u64) {
#[cfg(target_os = "windows")]
{
use std::process::Command;
let output = Command::new("wmic")
.args([
"OS",
"get",
"TotalVisibleMemorySize,FreePhysicalMemory",
"/Value",
])
.output()
.ok();
if let Some(output) = output {
if let Ok(text) = String::from_utf8(output.stdout) {
let mut total = 0u64;
let mut free = 0u64;
for line in text.lines() {
if let Some(value) = line.strip_prefix("TotalVisibleMemorySize=") {
total = value.trim().parse::<u64>().unwrap_or(0) * 1024;
} else if let Some(value) = line.strip_prefix("FreePhysicalMemory=") {
free = value.trim().parse::<u64>().unwrap_or(0) * 1024; }
}
if total > 0 {
return (total, free);
}
}
}
(8_000_000_000, 4_000_000_000)
}
#[cfg(target_os = "macos")]
{
use std::process::Command;
let total = Command::new("sysctl")
.arg("-n")
.arg("hw.memsize")
.output()
.ok()
.and_then(|output| String::from_utf8(output.stdout).ok())
.and_then(|s| s.trim().parse::<u64>().ok())
.unwrap_or(8_000_000_000);
let available = total / 2; (total, available)
}
#[cfg(target_os = "linux")]
{
use std::fs;
let mut total = 8_000_000_000u64;
let mut available = 4_000_000_000u64;
if let Ok(content) = fs::read_to_string("/proc/meminfo") {
for line in content.lines() {
if line.starts_with("MemTotal:") {
if let Some(kb) = line.split_whitespace().nth(1) {
if let Ok(kb_val) = kb.parse::<u64>() {
total = kb_val * 1024; }
}
} else if line.starts_with("MemAvailable:") {
if let Some(kb) = line.split_whitespace().nth(1) {
if let Ok(kb_val) = kb.parse::<u64>() {
available = kb_val * 1024; }
}
}
}
}
(total, available)
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
(8_000_000_000, 4_000_000_000) }
}
pub fn get_config_dir() -> Option<PathBuf> {
#[cfg(target_os = "windows")]
{
std::env::var("APPDATA")
.ok()
.map(|appdata| PathBuf::from(appdata).join("VoiRS"))
}
#[cfg(target_os = "macos")]
{
dirs::home_dir().map(|home| {
home.join("Library")
.join("Application Support")
.join("VoiRS")
})
}
#[cfg(target_os = "linux")]
{
std::env::var("XDG_CONFIG_HOME")
.ok()
.map(PathBuf::from)
.or_else(|| dirs::home_dir().map(|home| home.join(".config")))
.map(|config_dir| config_dir.join("voirs"))
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
dirs::home_dir().map(|home| home.join(".voirs"))
}
}
pub fn get_cache_dir() -> Option<PathBuf> {
#[cfg(target_os = "windows")]
{
std::env::var("LOCALAPPDATA")
.ok()
.map(|localappdata| PathBuf::from(localappdata).join("VoiRS").join("Cache"))
}
#[cfg(target_os = "macos")]
{
dirs::home_dir().map(|home| home.join("Library").join("Caches").join("VoiRS"))
}
#[cfg(target_os = "linux")]
{
std::env::var("XDG_CACHE_HOME")
.ok()
.map(PathBuf::from)
.or_else(|| dirs::home_dir().map(|home| home.join(".cache")))
.map(|cache_dir| cache_dir.join("voirs"))
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
dirs::home_dir().map(|home| home.join(".voirs").join("cache"))
}
}
pub fn get_data_dir() -> Option<PathBuf> {
#[cfg(target_os = "windows")]
{
std::env::var("LOCALAPPDATA")
.ok()
.map(|localappdata| PathBuf::from(localappdata).join("VoiRS").join("Data"))
}
#[cfg(target_os = "macos")]
{
dirs::home_dir().map(|home| {
home.join("Library")
.join("Application Support")
.join("VoiRS")
})
}
#[cfg(target_os = "linux")]
{
std::env::var("XDG_DATA_HOME")
.ok()
.map(PathBuf::from)
.or_else(|| dirs::home_dir().map(|home| home.join(".local").join("share")))
.map(|data_dir| data_dir.join("voirs"))
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
dirs::home_dir().map(|home| home.join(".voirs").join("data"))
}
}
pub fn ensure_platform_dirs() -> Result<(), Box<dyn std::error::Error>> {
if let Some(config_dir) = get_config_dir() {
std::fs::create_dir_all(&config_dir)?;
}
if let Some(cache_dir) = get_cache_dir() {
std::fs::create_dir_all(&cache_dir)?;
}
if let Some(data_dir) = get_data_dir() {
std::fs::create_dir_all(&data_dir)?;
}
Ok(())
}
pub fn is_elevated() -> bool {
#[cfg(target_os = "windows")]
{
use std::process::Command;
Command::new("net")
.args(["session"])
.output()
.map(|output| output.status.success())
.unwrap_or(false)
}
#[cfg(unix)]
{
unsafe { libc::geteuid() == 0 }
}
#[cfg(not(any(target_os = "windows", unix)))]
{
false
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_platform_info() {
let info = get_platform_info();
assert!(!info.os.is_empty());
assert!(!info.architecture.is_empty());
assert!(info.cpu_cores > 0);
assert!(info.total_memory > 0);
}
#[test]
fn test_platform_directories() {
assert!(get_config_dir().is_some());
assert!(get_cache_dir().is_some());
assert!(get_data_dir().is_some());
}
#[test]
fn test_ensure_directories() {
assert!(ensure_platform_dirs().is_ok());
}
}