1use yaml_rust::{Yaml};
2use yaml;
3use regex::{Regex, Captures};
4
5#[derive(Debug, PartialEq, Eq)]
7pub struct Device {
8 pub family: String,
9 pub brand: Option<String>,
10 pub model: Option<String>,
11 pub regex: Option<String>,
12}
13
14#[derive(Debug)]
15pub struct DeviceParser {
16 pub regex: Regex,
17 pub family: Option<String>,
18 pub brand: Option<String>,
19 pub model: Option<String>,
20}
21
22impl DeviceParser {
23 pub fn from_yaml(y: &Yaml) -> Option<DeviceParser> {
24 let regex_flag = yaml::string_from_map(y, "regex_flag");
25 yaml::string_from_map(y, "regex")
26 .map(|r|
27 if regex_flag.is_some() {
28 format!("(?i){}", r)
29 }else{
30 r
31 }
32 )
33 .map(|r| r.replace(r"\-", r"-"))
34 .map(|r| r.replace(r"\ ", r" "))
35 .map(|r| r.replace(r"\/", r"/"))
36 .and_then(|r| Regex::new(&r[..]).ok())
37 .map(|r| DeviceParser {
38 regex: r,
39 family: yaml::string_from_map(y, "device_replacement"),
40 brand: yaml::string_from_map(y, "brand_replacement"),
41 model: yaml::string_from_map(y, "model_replacement"),
42 })
43 }
44 fn replace(captures: &Captures, s: String) -> String {
45 captures.iter().zip((0..captures.len()))
46 .fold(s, |a, (c, i)| a.replace(&format!("${}", i)[..], c.unwrap_or("")))
47 .trim().to_string()
48 }
49
50 pub fn parse(&self, agent: String) -> Option<Device> {
51 self.regex.captures(&agent[..]).map(|c| {
52 let family = self.family.clone()
53 .map(|f| DeviceParser::replace(&c, f))
54 .unwrap_or(c.at(1).unwrap_or("Other").to_string());
55 let brand = self.brand.clone()
56 .map(|f| DeviceParser::replace(&c, f))
57 .or(c.at(1).map(|s| s.to_string()));
58 let model = self.model.clone()
59 .map(|f| DeviceParser::replace(&c, f))
60 .or(c.at(1).map(|s| s.to_string()));
61 Device {
62 family: family,
63 brand: brand,
64 model: model,
65 regex: Some(format!("{}", self.regex)),
66 }
67 })
68 }
69}