我正在尝试在Linux上解析/proc/cpuinfo
,并且遇到了一些麻烦。
我想退货:
我想将它们作为结构返回,但是我对所有返回它们的东西感到满意。
use std::{
collections::HashMap,
fmt,
fs::File,
io::{self, Read},
};
pub struct CPUInfo {
pub model_name: String,
pub cores: u16,
}
#[derive(Debug)]
pub enum Error {
UnsupportedSystem,
//ExecFailed(io::Error),
IO(io::Error),
Unknown,
}
impl fmt::Display for Error {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use self::Error::*;
match *self {
UnsupportedSystem => write!(fmt, "System is not supported"),
//ExecFailed(ref e) => write!(fmt, "Execution failed: {}", e),
IO(ref e) => write!(fmt, "IO error: {}", e),
Unknown => write!(fmt, "An unknown error occurred"),
}
}
}
impl std::error::Error for Error {
fn description(&self) -> &str {
use self::Error::*;
match *self {
UnsupportedSystem => "unsupported system",
//ExecFailed(_) => "execution failed",
IO(_) => "io error",
Unknown => "unknown error",
}
}
fn cause(&self) -> Option<&std::error::Error> {
use self::Error::*;
match *self {
UnsupportedSystem => None,
//ExecFailed(ref e) => Some(e),
IO(ref e) => Some(e),
Unknown => None,
}
}
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Error {
Error::IO(e)
}
}
pub fn get_cpu() -> Result<CPUInfo, Error> {
if cfg!(target_os = "linux") {
let mut s = String::new();
File::open("/proc/cpuinfo")?.read_to_string(&mut s)?;
let mut cpuinfo_hashmap = HashMap::new();
for line in s.lines() {
let mut split_line = line.split_whitespace();
let label = split_line.next();
let value = split_line.next();
if value.is_some() && label.is_some() {
let label = label.unwrap().split(':').nth(0).ok_or(Error::Unknown)?;
let value = value.unwrap().to_string();
cpuinfo_hashmap.insert(label, value.to_string());
}
}
Ok(CPUInfo {
model_name: {
let m = cpuinfo_hashmap.get("model name").ok_or(Error::Unknown)?;
m.to_string()
},
cores: {
let c = cpuinfo_hashmap.get("siblings").ok_or(Error::Unknown)?;
let cores: u16 = c.parse::<u16>().unwrap();
cores
},
})
} else {
Err(Error::UnsupportedSystem)
}
}
fn main() {
let cpu = get_cpu().expect("error getting cpu");
println!("CPU: {} {}", cpu.model_name, cpu.cores)
}
此代码失败:
thread 'main' panicked at 'error getting cpu: Unknown', libcore/result.rs:1009:5
note: Run with `RUST_BACKTRACE=1` for a backtrace.
然后Reddit上的某人建议使用derive_builder,所以我尝试了:
pub fn cpu_info() -> Result<CPUInfo, Error> {
let file = File::open("/proc/cpuinfo")?;
let buf_reader = BufReader::new(file);
let mut builder = &mut CPUInfoBuilder::default();
for line in buf_reader.lines() {
let line = line.unwrap();
let kv: Vec<_> = line.splitn(2, ':').map(|s| s.trim()).collect();
builder = match kv.as_slice() {
["model name", v] => builder.model_name(v.to_string()),
["cpu cores", v] => builder.cores(v.parse::<u16>().ok().ok_or(Error::Unknown)?),
[_, _] => builder,
[_] => builder,
_ => unreachable!(),
}
}
Ok(builder.build().expect("failed"))
}
还会编译并失败。
答案 0 :(得分:1)
您的代码有一些问题。我讨厌只为他们重写一个人的代码,但是即使编译成功后,您要做的某些事情也无法正常工作。下面的代码为您提供了一些指针。
以下代码可构建您期望的结构,打印到HashMap
进行调试,然后在结构中打印信息以方便查看:
use std::{
fs::File,
io::{BufRead, BufReader, Error, ErrorKind},
};
use hashbrown::HashMap;
fn main() {
let cpu = get_cpu().unwrap();
println!("{}{}", cpu.model_name, cpu.cores);
}
pub struct CPUInfo {
pub model_name: String,
pub cores: u16,
}
pub fn get_cpu() -> Result<CPUInfo, Error> {
if cfg!(target_os = "linux") {
let f = File::open("/proc/cpuinfo")?;
let reader = BufReader::new(f);
let mut cpuinfo_hashmap: HashMap<String, String> = HashMap::new();
for line in reader.lines().take(20) {
let line = line.unwrap();
let mut split_line = line.split(':');
let label = split_line.next();
let value = split_line.next();
if value.is_some() && label.is_some() {
let label = label.unwrap().trim().to_string();
let value = value.unwrap().trim().to_string();
cpuinfo_hashmap.insert(label, value);
}
}
println!("{:?}", cpuinfo_hashmap);
Ok(CPUInfo {
model_name: {
let m = cpuinfo_hashmap
.get("model name")
.ok_or(Error::from(ErrorKind::InvalidData))?;
m.clone()
},
cores: {
let c = cpuinfo_hashmap
.get("siblings")
.ok_or(Error::from(ErrorKind::InvalidData))?;
let cores: u16 = c.parse::<u16>().unwrap_or(0);
cores
},
})
} else {
Err(Error::from(ErrorKind::Other))
}
}
您的代码有问题:
BufRead
String
,需要直接BufRead
File
line
变量在使用前需要解开":"
字符上分割,这将为您提供一个HashMap
,其中包含20个看起来像"processor" : ":"
的条目