use std::collections::HashMap;
use std::io;
use std::ops::Deref;
use lazy_static::lazy_static;
use regex::Regex;
pub trait AttrFile<T, U: ?Sized = T>: ReadAttr<T> + WriteAttr<U> {}
pub trait ReadAttr<T> {
fn read(&self) -> io::Result<T>;
}
pub trait WriteAttr<T: ?Sized> {
fn write(&self, attr: &T) -> io::Result<()>;
}
impl<F, T, U> AttrFile<T, U> for F
where
F: ReadAttr<T> + WriteAttr<U>,
U: ?Sized,
{
}
pub trait ResetAttr {
fn reset(&self) -> io::Result<()>;
}
pub struct StatMap<'a>(HashMap<&'a str, &'a str>);
impl<'a> From<&'a str> for StatMap<'a> {
fn from(s: &'a str) -> StatMap<'a> {
lazy_static! {
static ref RE: Regex = Regex::new(r"(?m)^(?P<key>[_a-z]+) (?P<value>\d+)$").unwrap();
}
let mut res = HashMap::new();
for m in RE.captures_iter(s) {
res.insert(
m.name("key").unwrap().as_str(),
m.name("value").unwrap().as_str(),
);
}
StatMap(res)
}
}
impl<'a> Deref for StatMap<'a> {
type Target = HashMap<&'a str, &'a str>;
fn deref(&self) -> &HashMap<&'a str, &'a str> {
&self.0
}
}
macro_rules! stat_attr {
($map: ident, $stat: ident, [$($name: ident),+]) => {
$stat {
$($name: match $map.get(stringify!($name)).map(|s| s.parse()) {
Some(Ok($name)) => $name,
Some(Err(_)) | None => {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
format!("failed to parse {}", stringify!($name),),
));
}
},)*
}
};
}