linux_info/
memory.rs

1//!
2//! The data is retrieved from `/proc/meminfo`
3//!
4//! To list all availabe key's [linuxwiki.org](https://linuxwiki.org/proc/meminfo). Or you can use the api
5//! ```
6//! use linux_info::memory::Memory;
7//! let info = Memory::read().unwrap();
8//! let keys = info.keys();
9//! ```
10
11use crate::unit::DataSize;
12use crate::util::read_to_string_mut;
13
14use std::path::Path;
15use std::{fs, io};
16
17/// Read memory information from /proc/meminfo.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct Memory {
20	raw: String
21}
22
23impl Memory {
24
25	fn path() -> &'static Path {
26		Path::new("/proc/meminfo")
27	}
28
29	#[cfg(test)]
30	fn from_string(raw: String) -> Self {
31		Self {raw}
32	}
33
34	/// Read memory infos from /proc/meminfo.
35	pub fn read() -> io::Result<Self> {
36		Ok(Self {
37			raw: fs::read_to_string(Self::path())?
38		})
39	}
40
41	/// Reloads information without allocating.
42	pub fn reload(&mut self) -> io::Result<()> {
43		read_to_string_mut(Self::path(), &mut self.raw)
44	}
45
46	/// Get all key and values.
47	pub fn values<'a>(&'a self) -> impl Iterator<Item=(&'a str, &'a str)> {
48		self.raw.split('\n')
49			.filter_map(|line| {
50				// TODO: after 1.52 update tot split_once
51				let mut iter = line.splitn(2, ':');
52				let (key, value) = (iter.next()?, iter.next()?);
53				Some((key.trim(), value.trim()))
54			})
55	}
56
57	/// get all keys.
58	pub fn keys<'a>(&'a self) -> impl Iterator<Item=&'a str> {
59		self.values()
60			.map(|(k, _)| k)
61	}
62
63	/// Get value by key.
64	pub fn value<'a>(&'a self, key: &str) -> Option<&'a str> {
65		self.values()
66			.find_map(|(k, v)| k.eq_ignore_ascii_case(key).then(|| v))
67	}
68
69	/// Get size by key.
70	pub fn size_value<'a>(&'a self, key: &str) -> Option<DataSize> {
71		self.value(key)
72			.and_then(DataSize::from_str)
73	}
74
75	/// Returns the total memory.
76	pub fn total_memory(&self) -> Option<DataSize> {
77		self.size_value("MemTotal")
78	}
79
80	/// Returns the free memory.
81	pub fn free_memory(&self) -> Option<DataSize> {
82		self.size_value("MemFree")
83	}
84
85	/// Returns the available memory.
86	pub fn available_memory(&self) -> Option<DataSize> {
87		self.size_value("MemAvailable")
88	}
89
90}
91
92#[cfg(test)]
93mod tests {
94	use super::*;
95	use crate::unit::DataSizeUnit;
96
97	fn memory_info() -> Memory {
98		Memory::from_string("\
99MemTotal:       32853280 kB
100MemFree:          919776 kB
101MemAvailable:   28781828 kB
102Buffers:          298460 kB
103Cached:         27104800 kB
104SwapCached:          168 kB
105Active:          7764012 kB
106Inactive:       22289624 kB
107Active(anon):    2257064 kB
108Inactive(anon):   624500 kB
109Active(file):    5506948 kB
110Inactive(file): 21665124 kB
111Unevictable:          16 kB
112Mlocked:              16 kB
113SwapTotal:       2097148 kB
114SwapFree:        2094844 kB
115Dirty:               360 kB
116Writeback:             0 kB
117AnonPages:       2650504 kB
118Mapped:           760008 kB
119Shmem:            231188 kB
120KReclaimable:    1154740 kB
121Slab:            1529684 kB
122SReclaimable:    1154740 kB
123SUnreclaim:       374944 kB
124KernelStack:       21600 kB
125PageTables:        31948 kB
126NFS_Unstable:          0 kB
127Bounce:                0 kB
128WritebackTmp:          0 kB
129CommitLimit:    18523788 kB
130Committed_AS:    9191380 kB
131VmallocTotal:   34359738367 kB
132VmallocUsed:       62668 kB
133VmallocChunk:          0 kB
134Percpu:            37376 kB
135HardwareCorrupted:     0 kB
136AnonHugePages:         0 kB
137ShmemHugePages:        0 kB
138ShmemPmdMapped:        0 kB
139FileHugePages:         0 kB
140FilePmdMapped:         0 kB
141HugePages_Total:       0
142HugePages_Free:        0
143HugePages_Rsvd:        0
144HugePages_Surp:        0
145Hugepagesize:       2048 kB
146Hugetlb:               0 kB
147DirectMap4k:      922564 kB
148DirectMap2M:    10518528 kB
149DirectMap1G:    22020096 kB\
150		".into())
151	}
152
153	#[test]
154	fn total_memory() {
155		let mem_info = memory_info();
156		let total_memory = mem_info.total_memory().unwrap();
157		assert_eq!(total_memory.to(&DataSizeUnit::Kb), 32853280.0);
158	}
159
160}