use crate::error::{NeofetchError, Result};
use std::fmt::Display;
#[derive(Debug, Clone)]
pub struct Cpu {
pub name: String,
pub cores: u32,
pub speed: u32,
}
impl Display for Cpu {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let mut parts = vec![self.name.clone()];
if self.cores > 0 {
parts.push(format!("({})", self.cores));
}
if self.speed > 0 {
parts.push(format!("{:.2} GHz", self.speed as f64 / 1000.));
}
write!(f, "{}", parts.join(" "))
}
}
#[cfg(windows)]
pub async fn get_cpu() -> Result<Cpu> {
use serde::Deserialize;
use crate::platform::wmi_query;
#[derive(Deserialize, Debug, Clone)]
#[serde(rename = "Win32_Processor")]
struct Processor {
#[serde(rename = "Name")]
name: String,
#[serde(rename = "NumberOfLogicalProcessors")]
number_of_cores: u32,
#[serde(rename = "CurrentClockSpeed")]
current_clock_speed: u32,
}
let results: Vec<Processor> = wmi_query()
.await
.map_err(|e| NeofetchError::wmi_error(format!("WMI query failed: {}", e)))?;
results
.first()
.map(|proc| Cpu {
name: proc.name.trim().to_string(),
cores: proc.number_of_cores,
speed: proc.current_clock_speed,
})
.ok_or_else(|| NeofetchError::data_unavailable("No CPU information found"))
}
#[cfg(any(target_os = "linux", target_os = "macos"))]
pub async fn get_cpu() -> Result<Cpu> {
use crate::utils::{parse_proc_file, read_file_to_string};
let content = read_file_to_string("/proc/cpuinfo").await?;
let cpuinfo = parse_proc_file(&content);
let name = cpuinfo
.get("model name")
.or_else(|| cpuinfo.get("Hardware"))
.ok_or_else(|| NeofetchError::data_unavailable("CPU model name not found"))?
.to_string();
let mut cpu = Cpu {
name,
cores: 0,
speed: 0,
};
if let Some(mhz_str) = cpuinfo.get("cpu MHz")
&& let Ok(mhz) = mhz_str.parse::<f64>()
{
cpu.speed = mhz as u32;
}
if let Some(cores_str) = cpuinfo.get("cpu cores")
&& let Ok(cores) = cores_str.parse::<u32>()
{
cpu.cores = cores;
}
Ok(cpu)
}
#[cfg(target_os = "android")]
pub async fn get_cpu() -> Result<Cpu> {
use crate::utils::read_file_to_string;
let soc_model = crate::share::get_property("ro.soc.model")
.ok_or_else(|| NeofetchError::data_unavailable("SoC model property not found"))?;
let name = crate::share::detect_cpu(&soc_model)
.ok_or_else(|| NeofetchError::data_unavailable("CPU model not recognized"))?;
let mut cpu = Cpu {
name,
cores: 0,
speed: 0,
};
if let Ok(content) = read_file_to_string("/sys/devices/system/cpu/present").await {
if let Some((left, right)) = content.trim().split_once('-') {
if let (Ok(start), Ok(end)) = (left.parse::<u32>(), right.parse::<u32>()) {
cpu.cores = end - start + 1;
}
}
}
if cpu.cores > 0 {
let mut total_freq = 0u64;
let mut freq_count = 0u32;
for i in 0..cpu.cores {
let freq_path = format!("/sys/devices/system/cpu/cpu{}/cpufreq/scaling_cur_freq", i);
if let Ok(freq_str) = read_file_to_string(&freq_path).await {
if let Ok(freq) = freq_str.trim().parse::<u32>() {
total_freq += freq as u64;
freq_count += 1;
}
}
}
if freq_count > 0 {
cpu.speed = (total_freq / freq_count as u64 / 1024) as u32;
}
}
Ok(cpu)
}