#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Deserialize, Serialize)]
#[repr(transparent)]
pub struct MemoryInformation(pub(crate) HashMap<MemoryInformationName, u64>);
impl MemoryInformation
{
#[inline(always)]
pub fn parse_global(proc_path: &ProcPath, flush_per_cpu_statistics_first: bool) -> Result<Self, MemoryInformationParseError>
{
Self::parse(proc_path, b"", flush_per_cpu_statistics_first)
}
#[inline(always)]
pub(crate) fn parse(proc_path: &ProcPath, memory_information_name_prefix: &[u8], flush_per_cpu_statistics_first: bool) -> Result<Self, MemoryInformationParseError>
{
let file_path = proc_path.file_path("meminfo");
Self::parse_memory_information_file(&file_path, memory_information_name_prefix, if flush_per_cpu_statistics_first { Some(proc_path) } else { None })
}
#[inline]
pub fn get_statistic(&self, memory_information_name: &MemoryInformationName) -> Option<u64>
{
match self.0.get(memory_information_name)
{
None => None,
Some(value) => Some(*value),
}
}
#[inline(always)]
pub fn free_physical_ram(&self) -> Option<u64>
{
self.get_statistic(&MemoryInformationName::FreePhysicalRam)
}
#[inline]
pub fn used_physical_ram(&self) -> Option<u64>
{
if let Some(total_physical_ram) = self.get_statistic(&MemoryInformationName::TotalPhysicalRam)
{
if let Some(free_physical_ram) = self.get_statistic(&MemoryInformationName::FreePhysicalRam)
{
Some(total_physical_ram - free_physical_ram)
}
else
{
None
}
}
else
{
None
}
}
#[inline]
pub fn used_swap(&self) -> Option<u64>
{
if let Some(total_swap) = self.get_statistic(&MemoryInformationName::TotalSwap)
{
if let Some(free_swap) = self.get_statistic(&MemoryInformationName::FreeSwap)
{
Some(total_swap - free_swap)
}
else
{
None
}
}
else
{
None
}
}
pub(crate) fn parse_memory_information_file(file_path: &Path, memory_information_name_prefix: &[u8], flush_per_cpu_statistics_first: Option<&ProcPath>) -> Result<MemoryInformation, MemoryInformationParseError>
{
if let Some(proc_path) = flush_per_cpu_statistics_first
{
flush_per_cpu_statistics(proc_path)?;
}
let reader = file_path.read_raw()?;
let mut map = HashMap::new();
let mut zero_based_line_number = 0;
use self::MemoryInformationParseError::*;
for line in reader.split_bytes(b'\n')
{
let mut split = line.split_bytes_n(2, b':');
let memory_information_name = MemoryInformationName::parse(split.next().unwrap(), memory_information_name_prefix);
if map.contains_key(&memory_information_name)
{
return Err(DuplicateMemoryInformation { zero_based_line_number });
}
let raw_value = split.next().ok_or(NoValue { zero_based_line_number })?;
let bytes = memory_information_name.validate_unit(raw_value, zero_based_line_number)?;
let mut after_whitespace_index = 0;
while bytes[after_whitespace_index] == b' '
{
after_whitespace_index += 1;
if unlikely!(after_whitespace_index == raw_value.len())
{
return Err(TooMuchWhitespace { zero_based_line_number })
}
}
let bytes = &bytes[after_whitespace_index .. ];
let memory_information_value = u64::parse_decimal_number(bytes).map_err(|cause| BadValue { zero_based_line_number, cause })?;
map.insert(memory_information_name, memory_information_value);
zero_based_line_number += 1;
}
Ok(MemoryInformation(map))
}
}