use std::str;
use nom;
use nom::digit;
quick_error! {
#[derive(Debug)]
pub enum Error {
Parse {
display("Unable to parse vendor attribute")
}
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Type { HDD, SSD }
#[derive(Debug, Clone)]
pub struct Attribute {
pub id: Option<u8>,
pub name: Option<String>,
pub format: String,
pub byte_order: String,
pub drivetype: Option<Type>,
}
fn not_comma(c: u8) -> bool { c == b',' }
fn not_comma_nor_colon(c: u8) -> bool { c == b',' || c == b':' }
named!(parse_standard <Attribute>, do_parse!(
id: alt!(
map!(digit, |x: &[u8]| str::from_utf8(x).unwrap().parse::<u8>().ok())
| do_parse!(char!('N') >> (None))
) >>
char!(',') >>
format: map_res!(
take_till1_s!(not_comma_nor_colon),
str::from_utf8
) >>
byte_order: opt!(complete!(do_parse!( char!(':') >>
byteorder: map_res!(
take_till1_s!(not_comma),
str::from_utf8
) >>
(byteorder)
))) >>
name_drive_type: opt!(complete!(do_parse!(
char!(',') >>
name: map_res!(
take_till1_s!(not_comma),
str::from_utf8
) >>
drive_type: opt!(complete!(do_parse!(
char!(',') >>
drive_type: alt!(tag!("HDD") | tag!("SSD")) >>
(match str::from_utf8(drive_type) {
Ok("HDD") => Type::HDD,
Ok("SSD") => Type::SSD,
_ => unreachable!(),
})
))) >>
(name, drive_type)
))) >>
eof!() >>
({
let (name, drive_type) = match name_drive_type {
Some((name, drive_type)) => (Some(name), drive_type),
None => (None, None),
};
let default_byte_order = match format {
"raw64" | "hex64" => "543210wv",
"raw56" | "hex56" | "raw24/raw32" | "msec24hour32" => "r543210",
_ => "543210",
};
Attribute {
id: id,
name: name.map(|x| x.to_string()),
format: format.to_string(),
byte_order: byte_order.unwrap_or(default_byte_order).to_string(),
drivetype: drive_type,
}
})
));
pub fn parse(s: &str) -> Result<Attribute, Error> {
let s = match s {
"9,halfminutes" => "9,halfmin2hour,Power_On_Half_Minutes",
"9,minutes" => "9,min2hour,Power_On_Minutes",
"9,seconds" => "9,sec2hour,Power_On_Seconds",
"9,temp" => "9,tempminmax,Temperature_Celsius",
"192,emergencyretractcyclect" => "192,raw48,Emerg_Retract_Cycle_Ct",
"193,loadunload" => "193,raw24/raw24",
"194,10xCelsius" => "194,temp10x,Temperature_Celsius_x10",
"194,unknown" => "194,raw48,Unknown_Attribute",
"197,increasing" => "197,raw48+,Total_Pending_Sectors",
"198,offlinescanuncsectorct" => "198,raw48,Offline_Scan_UNC_SectCt", "198,increasing" => "198,raw48+,Total_Offl_Uncorrectabl",
"200,writeerrorcount" => "200,raw48,Write_Error_Count",
"201,detectedtacount" => "201,raw48,Detected_TA_Count",
"220,temp" => "220,tempminmax,Temperature_Celsius",
s => s,
};
match parse_standard(s.as_bytes()) {
nom::IResult::Done(_, attr) => Ok(attr),
nom::IResult::Error(_) => Err(Error::Parse), nom::IResult::Incomplete(_) => Err(Error::Parse), }
}