1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
pub(crate) mod types;
#[cfg(test)]
use super::mocks::CPUINFO;
pub(crate) use super::SysPath;
use crate::{Error, Result};
use std::{fmt::Display, str::FromStr};
pub use types::*;
pub(crate) const MODEL_NAME: &str = "model name";
pub(crate) const CACHE_SIZE: &str = "cache size";
pub(crate) const BOGOMIPS: &str = "bogomips";
pub(crate) const CPU_CORES: &str = "cpu cores";
pub(crate) const SIBLINGS: &str = "siblings";
pub(crate) const CPU_CLOCK: &str = "cpu MHz";
fn _cpuinfo_extract<T: FromStr>(out: &str, line: &str) -> Result<T>
where
<T as FromStr>::Err: Display,
{
Ok(out
.split('\n')
.filter(|l| l.starts_with(line))
.take(1)
.collect::<String>()
.split(':')
.skip(1)
.take(1)
.collect::<String>()
.trim()
.parse::<T>()
.map_err(|e| Error::CommandParseError(e.to_string()))?)
}
pub(crate) fn cpuinfo_extract<T: FromStr>(line: &str) -> Result<T>
where
<T as FromStr>::Err: Display,
{
_cpuinfo_extract(&SysPath::ProcCpuInfo.read()?, &line)
}
fn core_ids() -> Result<Vec<u32>> {
let mut core_ids = Vec::new();
for entry in SysPath::SysDevicesSystemCpu().read_dir()? {
if let Ok(entry) = entry {
let file_name = entry.file_name().to_string_lossy().to_string();
if !file_name.starts_with("cpu") {
continue;
}
if let Some(digits) = file_name.split("cpu").last() {
if let Some(digit) = digits.chars().next() {
if !digit.is_digit(10) {
continue;
}
core_ids.push(
u32::from_str_radix(digits, 10)
.map_err(|e| Error::InvalidInputError(file_name, e.to_string()))?,
);
}
}
}
}
Ok(core_ids)
}
pub fn cpu() -> Result<String> {
cpuinfo_extract::<String>(MODEL_NAME)
}
pub fn cpu_clock() -> Result<f32> {
cpuinfo_extract::<f32>(CPU_CLOCK)
}
pub fn cpu_cores() -> Result<u16> {
cpuinfo_extract::<u16>(CPU_CORES)
}
pub fn logical_cores() -> Result<u16> {
cpuinfo_extract::<u16>(SIBLINGS)
}
pub fn cores() -> Result<Cores> {
let mut cores = Vec::new();
for id in core_ids()? {
cores.push(Core::from_sys(id)?);
}
Ok(cores)
}
pub fn processor() -> Result<Processor> {
Processor::from_sys()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn extracts_cpuinfo() {
assert_eq!(_cpuinfo_extract::<u32>(CPUINFO, CPU_CORES), Ok(6));
assert_eq!(_cpuinfo_extract::<u32>(CPUINFO, SIBLINGS), Ok(12));
assert_eq!(_cpuinfo_extract::<f32>(CPUINFO, CPU_CLOCK), Ok(2053.971));
}
}