use crate::Result;
use serde::{Deserialize, Serialize};
use sysinfo::System;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum MemoryType {
DDR3,
DDR4,
DDR5,
LPDDR3,
LPDDR4,
LPDDR5,
Unknown(String),
}
impl std::fmt::Display for MemoryType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
MemoryType::DDR3 => write!(f, "DDR3"),
MemoryType::DDR4 => write!(f, "DDR4"),
MemoryType::DDR5 => write!(f, "DDR5"),
MemoryType::LPDDR3 => write!(f, "LPDDR3"),
MemoryType::LPDDR4 => write!(f, "LPDDR4"),
MemoryType::LPDDR5 => write!(f, "LPDDR5"),
MemoryType::Unknown(name) => write!(f, "{name}"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryModule {
pub size_mb: u64,
pub memory_type: MemoryType,
pub speed_mhz: u32,
pub manufacturer: Option<String>,
pub part_number: Option<String>,
pub slot: Option<String>,
pub voltage: Option<f32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryInfo {
pub total_mb: u64,
pub available_mb: u64,
pub used_mb: u64,
pub usage_percent: f32,
pub modules: Vec<MemoryModule>,
pub channels: u32,
pub ecc_support: bool,
pub speed_mhz: u32,
pub bandwidth_gb_s: Option<f32>,
pub swap_total_mb: u64,
pub swap_used_mb: u64,
}
impl MemoryInfo {
pub fn query() -> Result<Self> {
let mut system = System::new_all();
system.refresh_memory();
let total_mb = system.total_memory() / (1024 * 1024);
let available_mb = system.available_memory() / (1024 * 1024);
let used_mb = system.used_memory() / (1024 * 1024);
let usage_percent = (used_mb as f32 / total_mb as f32) * 100.0;
let swap_total_mb = system.total_swap() / (1024 * 1024);
let swap_used_mb = system.used_swap() / (1024 * 1024);
Ok(Self {
total_mb,
available_mb,
used_mb,
usage_percent,
modules: Self::detect_memory_modules()?,
channels: Self::detect_memory_channels()?,
ecc_support: Self::detect_ecc_support()?,
speed_mhz: Self::detect_memory_speed()?,
bandwidth_gb_s: Self::calculate_bandwidth(),
swap_total_mb,
swap_used_mb,
})
}
pub fn total_gb(&self) -> f64 {
self.total_mb as f64 / 1024.0
}
pub fn available_gb(&self) -> f64 {
self.available_mb as f64 / 1024.0
}
pub fn used_gb(&self) -> f64 {
self.used_mb as f64 / 1024.0
}
pub fn total_mb(&self) -> u64 {
self.total_mb
}
pub fn available_mb(&self) -> u64 {
self.available_mb
}
pub fn used_mb(&self) -> u64 {
self.used_mb
}
pub fn usage_percent(&self) -> f32 {
self.usage_percent
}
pub fn modules(&self) -> &[MemoryModule] {
&self.modules
}
pub fn channels(&self) -> u32 {
self.channels
}
pub fn ecc_support(&self) -> bool {
self.ecc_support
}
pub fn speed_mhz(&self) -> u32 {
self.speed_mhz
}
pub fn bandwidth_gb_s(&self) -> Option<f32> {
self.bandwidth_gb_s
}
pub fn swap_total_gb(&self) -> f64 {
self.swap_total_mb as f64 / 1024.0
}
pub fn swap_used_gb(&self) -> f64 {
self.swap_used_mb as f64 / 1024.0
}
pub fn has_sufficient_memory(&self, required_gb: f64) -> bool {
self.available_gb() >= required_gb
}
fn detect_memory_modules() -> Result<Vec<MemoryModule>> {
Ok(vec![MemoryModule {
size_mb: 8192,
memory_type: MemoryType::DDR4,
speed_mhz: 3200,
manufacturer: Some("Unknown".to_string()),
part_number: None,
slot: Some("DIMM1".to_string()),
voltage: Some(1.35),
}])
}
fn detect_memory_channels() -> Result<u32> {
Ok(2) }
fn detect_ecc_support() -> Result<bool> {
Ok(false)
}
fn detect_memory_speed() -> Result<u32> {
Ok(3200)
}
fn calculate_bandwidth() -> Option<f32> {
Some(51.2)
}
}