hardware_query/
memory.rs

1use crate::Result;
2use serde::{Deserialize, Serialize};
3use sysinfo::System;
4
5/// Memory type classification
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
7pub enum MemoryType {
8    DDR3,
9    DDR4,
10    DDR5,
11    LPDDR3,
12    LPDDR4,
13    LPDDR5,
14    Unknown(String),
15}
16
17impl std::fmt::Display for MemoryType {
18    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
19        match self {
20            MemoryType::DDR3 => write!(f, "DDR3"),
21            MemoryType::DDR4 => write!(f, "DDR4"),
22            MemoryType::DDR5 => write!(f, "DDR5"),
23            MemoryType::LPDDR3 => write!(f, "LPDDR3"),
24            MemoryType::LPDDR4 => write!(f, "LPDDR4"),
25            MemoryType::LPDDR5 => write!(f, "LPDDR5"),
26            MemoryType::Unknown(name) => write!(f, "{name}"),
27        }
28    }
29}
30
31/// Memory module information
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct MemoryModule {
34    /// Memory module size in MB
35    pub size_mb: u64,
36    /// Memory type
37    pub memory_type: MemoryType,
38    /// Memory speed in MHz
39    pub speed_mhz: u32,
40    /// Memory manufacturer
41    pub manufacturer: Option<String>,
42    /// Memory part number
43    pub part_number: Option<String>,
44    /// Memory slot location
45    pub slot: Option<String>,
46    /// Memory voltage
47    pub voltage: Option<f32>,
48}
49
50/// System memory information
51#[derive(Debug, Clone, Serialize, Deserialize)]
52pub struct MemoryInfo {
53    /// Total system memory in MB
54    pub total_mb: u64,
55    /// Available system memory in MB
56    pub available_mb: u64,
57    /// Used system memory in MB
58    pub used_mb: u64,
59    /// Memory usage percentage
60    pub usage_percent: f32,
61    /// Individual memory modules
62    pub modules: Vec<MemoryModule>,
63    /// Memory channels
64    pub channels: u32,
65    /// ECC support
66    pub ecc_support: bool,
67    /// Memory speed in MHz
68    pub speed_mhz: u32,
69    /// Memory bandwidth in GB/s
70    pub bandwidth_gb_s: Option<f32>,
71    /// Swap/virtual memory total in MB
72    pub swap_total_mb: u64,
73    /// Swap/virtual memory used in MB
74    pub swap_used_mb: u64,
75}
76
77impl MemoryInfo {
78    /// Query memory information from the system
79    pub fn query() -> Result<Self> {
80        let mut system = System::new_all();
81        system.refresh_memory();
82
83        let total_mb = system.total_memory() / (1024 * 1024);
84        let available_mb = system.available_memory() / (1024 * 1024);
85        let used_mb = system.used_memory() / (1024 * 1024);
86        let usage_percent = (used_mb as f32 / total_mb as f32) * 100.0;
87
88        let swap_total_mb = system.total_swap() / (1024 * 1024);
89        let swap_used_mb = system.used_swap() / (1024 * 1024);
90
91        Ok(Self {
92            total_mb,
93            available_mb,
94            used_mb,
95            usage_percent,
96            modules: Self::detect_memory_modules()?,
97            channels: Self::detect_memory_channels()?,
98            ecc_support: Self::detect_ecc_support()?,
99            speed_mhz: Self::detect_memory_speed()?,
100            bandwidth_gb_s: Self::calculate_bandwidth(),
101            swap_total_mb,
102            swap_used_mb,
103        })
104    }
105
106    /// Get total memory in GB
107    pub fn total_gb(&self) -> f64 {
108        self.total_mb as f64 / 1024.0
109    }
110
111    /// Get available memory in GB
112    pub fn available_gb(&self) -> f64 {
113        self.available_mb as f64 / 1024.0
114    }
115
116    /// Get used memory in GB
117    pub fn used_gb(&self) -> f64 {
118        self.used_mb as f64 / 1024.0
119    }
120
121    /// Get total memory in MB
122    pub fn total_mb(&self) -> u64 {
123        self.total_mb
124    }
125
126    /// Get available memory in MB
127    pub fn available_mb(&self) -> u64 {
128        self.available_mb
129    }
130
131    /// Get used memory in MB
132    pub fn used_mb(&self) -> u64 {
133        self.used_mb
134    }
135
136    /// Get memory usage percentage
137    pub fn usage_percent(&self) -> f32 {
138        self.usage_percent
139    }
140
141    /// Get memory modules
142    pub fn modules(&self) -> &[MemoryModule] {
143        &self.modules
144    }
145
146    /// Get number of memory channels
147    pub fn channels(&self) -> u32 {
148        self.channels
149    }
150
151    /// Check if ECC is supported
152    pub fn ecc_support(&self) -> bool {
153        self.ecc_support
154    }
155
156    /// Get memory speed in MHz
157    pub fn speed_mhz(&self) -> u32 {
158        self.speed_mhz
159    }
160
161    /// Get memory bandwidth in GB/s
162    pub fn bandwidth_gb_s(&self) -> Option<f32> {
163        self.bandwidth_gb_s
164    }
165
166    /// Get swap total in GB
167    pub fn swap_total_gb(&self) -> f64 {
168        self.swap_total_mb as f64 / 1024.0
169    }
170
171    /// Get swap used in GB
172    pub fn swap_used_gb(&self) -> f64 {
173        self.swap_used_mb as f64 / 1024.0
174    }
175
176    /// Check if system has sufficient memory for a workload
177    pub fn has_sufficient_memory(&self, required_gb: f64) -> bool {
178        self.available_gb() >= required_gb
179    }
180
181    fn detect_memory_modules() -> Result<Vec<MemoryModule>> {
182        // Platform-specific implementation would go here
183        // For now, return a placeholder module
184        Ok(vec![MemoryModule {
185            size_mb: 8192,
186            memory_type: MemoryType::DDR4,
187            speed_mhz: 3200,
188            manufacturer: Some("Unknown".to_string()),
189            part_number: None,
190            slot: Some("DIMM1".to_string()),
191            voltage: Some(1.35),
192        }])
193    }
194
195    fn detect_memory_channels() -> Result<u32> {
196        // Platform-specific implementation would go here
197        Ok(2) // Assume dual channel
198    }
199
200    fn detect_ecc_support() -> Result<bool> {
201        // Platform-specific implementation would go here
202        Ok(false)
203    }
204
205    fn detect_memory_speed() -> Result<u32> {
206        // Platform-specific implementation would go here
207        Ok(3200)
208    }
209
210    fn calculate_bandwidth() -> Option<f32> {
211        // Calculate theoretical bandwidth
212        // For DDR4-3200 dual channel: 3200 MHz * 2 channels * 8 bytes = 51.2 GB/s
213        Some(51.2)
214    }
215}