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
}
}