use crate::ProcResult;
use std::collections::HashMap;
#[derive(Debug)]
pub struct CpuInfo {
pub fields: HashMap<String, String>,
pub cpus: Vec<HashMap<String, String>>,
}
impl CpuInfo {
pub fn num_cores(&self) -> usize {
self.cpus.len()
}
pub fn get_info(&self, cpu_num: usize) -> Option<HashMap<&str, &str>> {
if let Some(info) = self.cpus.get(cpu_num) {
let mut map = HashMap::new();
for (k, v) in &self.fields {
map.insert(k.as_ref(), v.as_ref());
}
for (k, v) in info.iter() {
map.insert(k.as_ref(), v.as_ref());
}
Some(map)
} else {
None
}
}
pub fn model_name(&self, cpu_num: usize) -> Option<&str> {
self.get_info(cpu_num)
.and_then(|mut m| m.remove("model name"))
}
pub fn vendor_id(&self, cpu_num: usize) -> Option<&str> {
self.get_info(cpu_num)
.and_then(|mut m| m.remove("vendor_id"))
}
pub fn physical_id(&self, cpu_num: usize) -> Option<u32> {
self.get_info(cpu_num)
.and_then(|mut m| m.remove("vendor_id"))
.and_then(|s| u32::from_str_radix(s, 10).ok())
}
pub fn flags(&self, cpu_num: usize) -> Option<Vec<&str>> {
self.get_info(cpu_num)
.and_then(|mut m| m.remove("flags"))
.map(|flags: &str| flags.split_whitespace().collect())
}
}
pub fn cpuinfo() -> ProcResult<CpuInfo> {
use std::fs::File;
use std::io::{BufRead, BufReader};
let file = File::open("/proc/cpuinfo")?;
let reader = BufReader::new(file);
let mut list = Vec::new();
let mut map = Some(HashMap::new());
for line in reader.lines() {
if let Ok(line) = line {
if !line.is_empty() {
let mut s = line.split(':');
let key = s.next().unwrap();
if let Some(value) = s.next() {
let key = key.trim().to_owned();
let value = value.trim().to_owned();
map.get_or_insert(HashMap::new()).insert(key, value);
}
} else if let Some(map) = map.take() {
list.push(map);
}
}
}
if let Some(map) = map.take() {
list.push(map);
}
assert!(!list.is_empty());
let common_fields: Vec<String> = list[0]
.iter()
.filter_map(|(key, val)| {
if list
.iter()
.all(|map| map.get(key).map_or(false, |v| v == val))
{
Some(key.clone())
} else {
None
}
})
.collect();
let mut common_map = HashMap::new();
for (k, v) in &list[0] {
if common_fields.contains(k) {
common_map.insert(k.clone(), v.clone());
}
}
for map in &mut list {
map.retain(|k, _| !common_fields.contains(k));
}
print!("{:?}", common_fields);
Ok(CpuInfo {
fields: common_map,
cpus: list,
})
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_cpuinfo() {
let info = cpuinfo().unwrap();
println!("{:#?}", info.flags(0));
}
}