procstat 1.0.4

Parses the /proc/stat file into a struct.
Documentation
#![crate_type = "lib"]
#![crate_name = "procstat"]

use std::collections::HashMap;
use std::{fs::File, io::{BufRead, BufReader}, path::Path};

mod boot_time;
mod cpu;
mod contexts;
mod interrupts;
mod processes;
mod soft_irq;

pub use boot_time::*;
pub use cpu::*;
pub use contexts::*;
pub use interrupts::*;
pub use processes::*;
pub use soft_irq::*;

#[derive(Debug)]
pub struct ProcStat {
    pub cpu: CPU,
    pub cpus: HashMap<usize,CPU>,
    pub interrupts: Interrupts,
    pub contexts: Contexts,
    pub boot_time: BootTime,
    pub processes: Processes,
    pub soft_irq: SoftIrq,
}

const KEY_CPU: &str = "cpu";
const KEY_INTERRUPTS: &str = "intr";
const KEY_CONTEXTS: &str = "ctxt";
const KEY_BOOT_TIME: &str = "btime";
const KEY_SOFT_IRQ: &str = "softirq";
const KEY_PROCESSES: &str = "processes";
const KEY_PROCESSES_RUNNING: &str = "procs_running";
const KEY_PROCESSES_BLOCKED: &str = "procs_blocked";

impl ProcStat {
    fn empty() -> Self {
        Self {
            cpu: CPU::empty(),
            cpus: HashMap::new(),
            interrupts: Interrupts::empty(),
            contexts: Contexts::empty(),
            boot_time: BootTime::empty(),
            processes: Processes::empty(),
            soft_irq: SoftIrq::empty(),
        }
    }

    pub fn read() -> ProcStat {

        let file = File::open(Path::new("/proc/stat")).unwrap();
        
        ProcStat::read_file(file)
    }

    pub fn read_file(file: File) -> ProcStat {
        let mut proc_stat = Self::empty();

        let reader = BufReader::new(file);
        for line in reader.lines() {
            let line = line.unwrap();
            let mut tokenised = line.split_whitespace();
            let key = tokenised.next().unwrap_or("");
            let values: Vec<u64> = tokenised.by_ref().map(|t| u64::from_str_radix(t, 10).unwrap_or_default()).collect();

            if key.eq(KEY_CPU) {
                proc_stat.cpu = CPU::from_vec(values);
            } else if key.starts_with(KEY_CPU) {
                let cpu = CPU::from_vec(values);
                let cpu_index = usize::from_str_radix(key.split_at(3).1, 10).unwrap();
                proc_stat.cpus.insert(cpu_index, cpu);
            } else if key.eq(KEY_INTERRUPTS) {
                proc_stat.interrupts = Interrupts::from_vec(values);
            } else if key.eq(KEY_CONTEXTS) {
                proc_stat.contexts = Contexts::from_vec(values);
            } else if key.eq(KEY_BOOT_TIME) {
                proc_stat.boot_time = BootTime::from_vec(values);
            } else if key.eq(KEY_SOFT_IRQ) {
                proc_stat.soft_irq = SoftIrq::from_vec(values);
            } else if key.eq(KEY_PROCESSES) {
                proc_stat.processes.forks_since_boot = *values.first().unwrap();
            } else if key.eq(KEY_PROCESSES_RUNNING) {
                proc_stat.processes.running_processes = *values.first().unwrap();
            } else if key.eq(KEY_PROCESSES_BLOCKED) {
                proc_stat.processes.blocked_processes = *values.first().unwrap();
            }
        }

        proc_stat
    }
}