1use {
2 crate::*,
3 std::{
4 fs::File,
5 io::Read,
6 },
7};
8
9pub struct ProcStatus {
14 content: String,
15}
16
17impl ProcStatus {
18
19 pub fn read() -> Result<Self, ProcStatusError> {
23 Self::read_for(ProcRef::ProcSelf)
24 }
25
26 pub fn read_for(proc_ref: ProcRef) -> Result<Self, ProcStatusError> {
28 let mut file = match proc_ref {
29 ProcRef::ProcSelf => File::open("/proc/self/status"),
30 ProcRef::ProcId(id) => File::open(format!("/proc/{}/status", id)),
31 }?;
32 let mut content = String::new();
33 file.read_to_string(&mut content)?;
34 Ok(Self { content })
35 }
36
37 pub fn entries(&self) -> ProcEntries<'_> {
39 ProcEntries::from_content(&self.content)
40 }
41
42 pub fn entry(&self, key: &str) -> Result<ProcEntry<'_>, ProcStatusError> {
44 for entry in self.entries() {
45 let entry = entry?;
46 if entry.key == key {
47 return Ok(entry);
48 }
49 }
50 Err(ProcStatusError::EntryNotFound(key.to_string()))
51 }
52
53 pub fn value(&self, key: &str) -> Result<&str, ProcStatusError> {
65 self.entry(key).map(|e| e.value)
66 }
67
68 #[allow(non_snake_case)]
70 pub fn value_KiB(&self, key: &str) -> Result<usize, ProcStatusError> {
71 self.entry(key).and_then(|e| e.in_KiB())
72 }
73
74 pub fn mem_usage(&self) -> Result<MemUsage, ProcStatusError> {
76 self.value_KiB("VmRSS")
77 .and_then(|current| {
78 self.value_KiB("VmPeak")
79 .map(|peak| MemUsage {
80 current: current * 1024, peak: peak * 1024,
82 })
83 })
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 #[test]
91 fn test_read() {
92 let ps = ProcStatus::read().unwrap();
93 let name = ps.value("Name").unwrap();
94 println!("name: {:?}", name);
95 println!("VM peak: {:?}", ps.value("VmPeak").unwrap());
96 println!("VM peak KiB: {:?}", ps.entry("VmPeak").unwrap().in_KiB().unwrap());
97 mem_usage().unwrap();
98 }
99}