use std::fs::File;
use std::io::{Error, ErrorKind, Result};
use std::os::unix::raw::pid_t;
use nom::{IResult, digit, line_ending, space};
use parsers::{parse_usize, read_to_end};
#[derive(Debug, Default, PartialEq, Eq, Hash)]
pub struct Statm {
pub size: usize,
pub resident: usize,
pub share: usize,
pub text: usize,
pub data: usize,
}
named!(parse_statm<Statm>,
chain!(
size: parse_usize ~ space ~
resident: parse_usize ~ space ~
share: parse_usize ~ space ~
text: parse_usize ~ space ~
digit ~ space ~ data: parse_usize ~ space ~
digit ~ line_ending, || { Statm { size: size,
resident: resident,
share: share,
text: text,
data: data } }));
fn statm_file(file: &mut File) -> Result<Statm> {
let mut buf = [0; 256]; match parse_statm(try!(read_to_end(file, &mut buf))) {
IResult::Done(_, statm) => Ok(statm),
_ => Err(Error::new(ErrorKind::InvalidData, "unable to parse statm file")),
}
}
pub fn statm(pid: pid_t) -> Result<Statm> {
statm_file(&mut try!(File::open(&format!("/proc/{}/statm", pid))))
}
pub fn statm_self() -> Result<Statm> {
statm_file(&mut try!(File::open("/proc/self/statm")))
}
#[cfg(test)]
mod tests {
extern crate test;
use std::fs::File;
use std::str;
use nom::IResult;
use parsers::read_to_end;
use super::{Statm, parse_statm, statm, statm_self};
#[test]
fn test_statm() {
statm_self().unwrap();
let Statm { size, resident, share, text, data } = statm(1).unwrap();
assert!(size != 0);
assert!(resident != 0);
assert!(share != 0);
assert!(text != 0);
assert!(data != 0);
}
#[test]
fn test_parse_statm() {
let mut buf = [0; 256];
let status = read_to_end(&mut File::open("/proc/1/statm").unwrap(), &mut buf).unwrap();
match parse_statm(status) {
IResult::Done(remaining, _) => {
if !remaining.is_empty() {
panic!(format!("Unable to parse whole status file, remaining:\n{}",
str::from_utf8(remaining).unwrap()));
}
}
_ => panic!("unable to unwrap IResult"),
}
}
#[bench]
fn bench_statm(b: &mut test::Bencher) {
b.iter(|| test::black_box(statm(1)));
}
#[bench]
fn bench_parse_statm(b: &mut test::Bencher) {
let mut buf = [0; 256];
let statm = read_to_end(&mut File::open("/proc/1/statm").unwrap(), &mut buf).unwrap();
b.iter(|| test::black_box(parse_statm(statm)));
}
}