use std::num::ParseIntError;
use std::ops::{Deref, DerefMut, Range};
use std::{error, fmt, str};
#[derive(Debug)]
pub struct ParseSizeError {
pub(crate) label: String,
pub(crate) size: String,
pub(crate) source: ParseIntError,
}
impl ParseSizeError {
#[inline]
fn new(label: &str, size: &str, source: ParseIntError) -> Self {
Self {
label: label.to_owned(),
size: size.to_owned(),
source,
}
}
}
impl fmt::Display for ParseSizeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_fmt(format_args!(
"failed to parse `{size}` as usize in `/proc/meminfo` entry `{label}`",
size = self.size,
label = self.label
))
}
}
impl error::Error for ParseSizeError {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
Some(&self.source)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MemInfoEntry<'m> {
pub(crate) label: &'m str,
pub(crate) size: &'m str,
pub(crate) unit: Option<&'m str>,
}
impl<'m> MemInfoEntry<'m> {
pub(crate) const DELIMITER: u8 = b':';
#[inline]
#[cfg(not(feature = "utf8-unchecked"))]
pub(crate) fn new(label: &'m [u8], size: &'m [u8], unit: Option<&'m [u8]>) -> Self {
#[inline(always)]
fn from_utf8(bytes: &[u8]) -> &str {
str::from_utf8(bytes).expect("`/proc/meminfo` to contain valid UTF-8")
}
Self {
label: from_utf8(label),
size: from_utf8(size),
unit: unit.map(from_utf8),
}
}
#[inline]
#[must_use]
#[cfg(feature = "utf8-unchecked")]
pub(crate) unsafe fn new_unchecked(
label: &'m [u8],
size: &'m [u8],
unit: Option<&'m [u8]>,
) -> Self {
Self {
label: unsafe { str::from_utf8_unchecked(label) },
size: unsafe { str::from_utf8_unchecked(size) },
unit: unit.map(|unit| unsafe { str::from_utf8_unchecked(unit) }),
}
}
#[inline]
#[must_use]
pub fn label(&self) -> &str {
self.label
}
#[inline]
pub fn size(&self) -> Result<usize, ParseSizeError> {
self.size
.parse()
.map_err(|source| ParseSizeError::new(self.label, self.size, source))
}
#[inline]
#[must_use]
pub fn unit(&self) -> Option<&str> {
self.unit
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct MemInfoEntryExtended<'m> {
pub(crate) entry: MemInfoEntry<'m>,
pub(crate) range: Range<usize>,
}
impl<'m> MemInfoEntryExtended<'m> {
#[inline]
pub(crate) fn new(entry: MemInfoEntry<'m>, start: usize, end: usize) -> Self {
Self {
entry,
range: start..end,
}
}
#[inline]
#[must_use]
pub fn byte_range(&self) -> &Range<usize> {
&self.range
}
#[inline]
#[must_use]
pub fn start_pos(&self) -> usize {
self.range.start
}
#[inline]
#[must_use]
pub fn end_pos(&self) -> usize {
self.range.end
}
#[inline]
#[must_use]
pub fn required_capacity(&self) -> usize {
self.range.end - self.range.start
}
}
impl<'m> Deref for MemInfoEntryExtended<'m> {
type Target = MemInfoEntry<'m>;
fn deref(&self) -> &Self::Target {
&self.entry
}
}
impl<'m> DerefMut for MemInfoEntryExtended<'m> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.entry
}
}