infomgr 0.2.2

Show system information.
Documentation
use serde::{Deserialize, Serialize};
use std::fmt;
use std::fs;
use std::io::{BufRead, BufReader};

#[derive(Deserialize, Serialize, Debug, Copy, Clone, Default)]
pub struct MemoryReport {
    pub total: Option<u64>,
    pub free: Option<u64>,
    pub anon: Option<u64>,
    pub file: Option<u64>,
    pub avail: Option<u64>,
    pub buffer: Option<u64>,
    pub cached: Option<u64>,
    pub unevictable: Option<u64>,
    pub cmatotal: Option<u64>,
    pub cmafree: Option<u64>,
    pub slab: Option<u64>,
    pub slab_rec: Option<u64>,
    pub slab_unrec: Option<u64>,
    pub shmem: Option<u64>,
}

impl fmt::Display for MemoryReport {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let mut s: Vec<String> = Vec::new();

        if let Some(a) = self.total {
            s.push(format!("{} total,", a));
        }

        if let Some(a) = self.free {
            s.push(format!("{} free,", a));
        }

        if let Some(a) = self.avail {
            s.push(format!("{} avail,", a));
        }

        if let Some(a) = self.anon {
            s.push(format!("{} anon,", a));
        }

        if let Some(a) = self.file {
            s.push(format!("{} file,", a));
        }

        if let Some(a) = self.buffer {
            s.push(format!("{} buffer,", a));
        }

        if let Some(a) = self.cached {
            s.push(format!("{} cached,", a));
        }

        if let Some(a) = self.unevictable {
            s.push(format!("{} unevict,", a));
        }

        if let Some(a) = self.cmatotal {
            s.push(format!("{} cma,", a));
        }

        if let Some(a) = self.cmafree {
            s.push(format!("{} cmafree,", a));
        }

        if let Some(a) = self.slab {
            s.push(format!("{} slab,", a));
        }

        if let Some(a) = self.slab_unrec {
            s.push(format!("{} slab_unrec,", a));
        }

        if let Some(a) = self.shmem {
            s.push(format!("{} shmem,", a));
        }

        write!(f, "Memory(kb): {}", s.join(" ").trim_end_matches(','))
    }
}

pub struct MemInfo {}

impl MemInfo {
    pub fn load() -> MemoryReport {
        let mut mr: MemoryReport = Default::default();

        if let Ok(f) = fs::OpenOptions::new().read(true).open("/proc/meminfo") {
            let mut reader = BufReader::new(f);

            loop {
                let mut line = String::new();

                if reader.read_line(&mut line).is_err() {
                    break;
                }

                if line.trim().is_empty() {
                    break;
                }

                let mut entries = line.split_whitespace();

                let (name, size_kb) = (
                    entries.next().unwrap().trim(),
                    entries.next().unwrap().parse::<u64>().unwrap(),
                );

                match name {
                    "MemTotal:" => mr.total = Some(size_kb),
                    "MemFree:" => mr.free = Some(size_kb),
                    "Active(anon):" => {
                        mr.anon = Some(mr.anon.take().map_or(size_kb, |v| v + size_kb))
                    }
                    "Inactive(anon):" => {
                        mr.anon = Some(mr.anon.take().map_or(size_kb, |v| v + size_kb))
                    }
                    "Active(file):" => {
                        mr.file = Some(mr.file.take().map_or(size_kb, |v| v + size_kb))
                    }
                    "Inactive(file):" => {
                        mr.file = Some(mr.file.take().map_or(size_kb, |v| v + size_kb))
                    }
                    "MemAvailable:" => mr.avail = Some(size_kb),
                    "Buffers:" => mr.buffer = Some(size_kb),
                    "Cached:" => mr.cached = Some(size_kb),
                    "Unevictable:" => mr.unevictable = Some(size_kb),
                    "CmaTotal:" => mr.cmatotal = Some(size_kb),
                    "CmaFree:" => mr.cmafree = Some(size_kb),
                    "Slab:" => mr.slab = Some(size_kb),
                    "SReclaimable:" => mr.slab_rec = Some(size_kb),
                    "SUnreclaim:" => mr.slab_unrec = Some(size_kb),
                    "Shmem:" => mr.shmem = Some(size_kb),
                    _ => {}
                }
            }
        }
        mr
    }
}