use crate::stat::Cpu;
use crate::stat::Stat;
use crate::util::find_to_opt;
use crate::util::find_to_pos;
use cfg_iif::cfg_iif;
#[derive(Debug, Default, Clone)]
pub struct StatParser {
cpus_cap: usize,
}
impl StatParser {
pub fn parse(&mut self, sl: &[u8]) -> Stat {
let mut stat = if self.cpus_cap > 0 {
Stat::with_capacity(self.cpus_cap)
} else {
Stat::default()
};
if sl.is_empty() {
return stat;
}
let mut pos1: usize = 0;
let mut pos2: usize;
let mut pos_end: usize;
let haystack = &sl[pos1..];
let needle = b"cpu ";
pos1 = pos1 + needle.len() + find_to_pos(haystack, needle);
stat.cpu.name = "cpu".to_string();
let haystack = &sl[pos1..];
let needle = b"\n";
pos_end = pos1
+ 1
+ match find_to_opt(haystack, needle) {
Some(pos) => pos,
None => unreachable!(),
};
macro_rules! myscan {
(check, $needle:expr) => {{
{
let haystack = &sl[pos1..pos_end];
let needle = $needle;
match find_to_opt(haystack, needle) {
Some(_pos) => true,
None => false,
}
}
}};
(skip, $needle:expr) => {{
pos2 = {
let haystack = &sl[pos1..pos_end];
let needle = $needle;
pos1 + find_to_pos(haystack, needle)
};
let s = &sl[pos1..pos2];
pos1 = pos2 + 1;
s
}};
($needle:expr) => {{
let s = myscan!(skip, $needle);
let input = String::from_utf8_lossy(s);
input.as_ref().parse().unwrap()
}};
}
{
stat.cpu.user = myscan!(b" ");
stat.cpu.nice = myscan!(b" ");
stat.cpu.system = myscan!(b" ");
stat.cpu.idle = myscan!(b" ");
stat.cpu.iowait = myscan!(b" ");
stat.cpu.irq = myscan!(b" ");
stat.cpu.softirq = myscan!(b" ");
if !myscan!(check, b" ") {
stat.cpu.steal = myscan!(b"\n");
} else {
stat.cpu.steal = myscan!(b" ");
stat.cpu.guest = myscan!(b" ");
stat.cpu.guest_nice = myscan!(b"\n");
}
let _ = pos1;
}
'cpu_lp: loop {
let haystack = &sl[pos1..];
let needle = b"cpu";
pos1 = pos1
+ needle.len()
+ match find_to_opt(haystack, needle) {
Some(pos) => pos,
None => break 'cpu_lp,
};
let haystack = &sl[pos1..];
let needle = b"\n";
pos_end = pos1
+ 1
+ match find_to_opt(haystack, needle) {
Some(pos) => pos,
None => unreachable!(),
};
let idx: usize = myscan!(b" ");
if idx >= stat.cpus.len() {
stat.cpus.resize(idx + 1, Cpu::default());
}
let cpu_ref: &mut Cpu = match stat.cpus.get_mut(idx) {
Some(cpu) => cpu,
None => unreachable!(),
};
cpu_ref.name = format!("cpu{idx}");
cpu_ref.user = myscan!(b" ");
cpu_ref.nice = myscan!(b" ");
cpu_ref.system = myscan!(b" ");
cpu_ref.idle = myscan!(b" ");
cpu_ref.iowait = myscan!(b" ");
cpu_ref.irq = myscan!(b" ");
cpu_ref.softirq = myscan!(b" ");
if !myscan!(check, b" ") {
cpu_ref.steal = myscan!(b"\n");
} else {
cpu_ref.steal = myscan!(b" ");
cpu_ref.guest = myscan!(b" ");
cpu_ref.guest_nice = myscan!(b"\n");
}
let _ = pos1;
}
macro_rules! myscan {
(skip, $needle:expr) => {{
pos2 = {
let haystack = &sl[pos1..];
let needle = $needle;
pos1 + find_to_pos(haystack, needle)
};
let s = &sl[pos1..pos2];
pos1 = pos2 + 1;
s
}};
($needle:expr) => {{
let s = myscan!(skip, $needle);
let input = String::from_utf8_lossy(s);
input.as_ref().parse().unwrap()
}};
}
{
let haystack = &sl[pos1..];
let needle = b"ctxt ";
pos1 = pos1 + needle.len() + find_to_pos(haystack, needle);
stat.ctxt = myscan!(b"\n");
}
cfg_iif!(feature = "has_stat_btime" {
let haystack = &sl[pos1..];
let needle = b"btime ";
pos1 = pos1 + needle.len() + find_to_pos(haystack, needle);
stat.btime = myscan!(b"\n");
});
{
let haystack = &sl[pos1..];
let needle = b"processes ";
pos1 = pos1 + needle.len() + find_to_pos(haystack, needle);
stat.processes = myscan!(b"\n");
}
cfg_iif!(feature = "has_stat_procs_running" {
let haystack = &sl[pos1..];
let needle = b"procs_running ";
pos1 = pos1 + needle.len() + find_to_pos(haystack, needle);
stat.procs_running = myscan!(b"\n");
});
cfg_iif!(feature = "has_stat_procs_blocked" {
let haystack = &sl[pos1..];
let needle = b"procs_blocked ";
pos1 = pos1 + needle.len() + find_to_pos(haystack, needle);
stat.procs_blocked = myscan!(b"\n");
});
let _ = pos1;
stat.cpus.shrink_to_fit();
self.cpus_cap = stat.cpus.len();
stat
}
}