define_struct! {
pub struct Module {
name: String,
mem_size: usize,
instance_nums: usize,
deps: Vec<String>,
state: State,
offset: usize,
}
}
use std::str::FromStr;
impl FromStr for Module {
type Err = crate::ProcErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let columns: Vec<&str> = s.split_ascii_whitespace().collect();
if columns.len() != 6 {
return Err("require 6 items to parse module".into());
}
let name = columns[0].to_string();
let mem_size = columns[1].parse::<usize>()?;
let instance_nums = columns[2].parse::<usize>()?;
let deps: Vec<String> = if columns[3] == "-" {
Vec::new()
} else {
let mut v: Vec<String> = columns[3].split(',').map(|s| s.to_string()).collect();
v.pop();
v
};
let state = State::from_str(columns[4])?;
let offset = usize::from_str_radix(columns[5].trim_start_matches("0x"), 16)?;
Ok(Module {
name,
mem_size,
instance_nums,
deps,
state,
offset,
})
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum State {
Live,
Loading,
Unloading,
}
impl FromStr for State {
type Err = crate::ProcErr;
fn from_str(s: &str) -> Result<Self, Self::Err> {
if s == "Live" {
Ok(State::Live)
} else if s == "Loading" {
Ok(State::Loading)
} else if s == "Unloading" {
Ok(State::Unloading)
} else {
Err("unknow stat".into())
}
}
}
list_impl! {
modules, "/proc/modules", Module, '\n', 0
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_parse_state() {
assert_eq!(State::Live, "Live".parse().unwrap());
assert_eq!(State::Loading, "Loading".parse().unwrap());
assert_eq!(State::Unloading, "Unloading".parse().unwrap());
assert!("XYZ".parse::<State>().is_err())
}
#[test]
fn test_parse_module1() {
let source = "sbhid 53248 0 - Live 0x0000000000000000";
let correct = Module{
name: "sbhid".to_string(),
mem_size: 53248,
instance_nums: 0,
deps: vec![],
state: State::Live,
offset: 0,
};
assert_eq!(correct, source.parse().unwrap());
}
#[test]
fn test_parse_module2() {
let source = "hid 110592 2 hid_generic,usbhid, Live 0x0000000000000000";
let correct = Module {
name: "hid".to_string(),
mem_size: 110592,
instance_nums: 2,
deps: vec!["hid_generic".to_string(), "usbhid".to_string()],
state: State::Live,
offset: 0
};
assert_eq!(correct, source.parse().unwrap());
}
}