uap_rust/
os.rs

1use yaml_rust::{Yaml};
2use yaml;
3use regex::Regex;
4
5///`OS` contains the operating system information from the user agent.
6#[derive(Debug, PartialEq, Eq)]
7pub struct OS {
8    pub family: String,
9    pub major: Option<String>,
10    pub minor: Option<String>,
11    pub patch: Option<String>,
12    pub patch_minor: Option<String>,
13}
14
15#[derive(Debug)]
16pub struct OSParser {
17    pub regex: Regex,
18    pub family: Option<String>,
19    pub major: Option<String>,
20    pub minor: Option<String>,
21    pub patch: Option<String>,
22    pub patch_minor: Option<String>,
23}
24
25impl OSParser {
26    pub fn from_yaml(y: &Yaml) -> Option<OSParser> {
27            yaml::string_from_map(y, "regex")
28            .map(|r| r.replace(r"\-", r"-"))
29            .map(|r| r.replace(r"\ ", r" "))
30            .map(|r| r.replace(r"\/", r"/"))
31            .and_then(|r| Regex::new(&r[..]).ok())
32            .map(|r| OSParser {
33                regex: r,
34                family: yaml::string_from_map(y, "os_replacement"),
35                major: yaml::string_from_map(y, "os_v1_replacement"),
36                minor: yaml::string_from_map(y, "os_v2_replacement"),
37                patch: yaml::string_from_map(y, "os_v3_replacement"),
38                patch_minor: yaml::string_from_map(y, "os_v4_replacement"),
39            })
40    }
41
42    pub fn parse(&self, agent: String) -> Option<OS> {
43        self.regex.captures(&agent[..]).map(|c| {
44            let family = self.family.clone()
45                .and_then(|f| c.at(1).map(|a| f.replace("$1", a)))
46                .unwrap_or(c.at(1).unwrap_or("Other").to_string());
47            let major = self.major.clone()
48                .and_then(|f| c.at(2).map(|a| f.replace("$2", a)))
49                .or(c.at(2).map(String::from));
50            let minor = self.minor.clone()
51                .and_then(|f| c.at(3).map(|a| f.replace("$3", a)))
52                .or(c.at(3).map(String::from));
53            let patch = self.patch.clone()
54                .and_then(|f| c.at(4).map(|a| f.replace("$4", a)))
55                .or(c.at(4).map(String::from));
56            let patch_minor = self.patch_minor.clone()
57                .and_then(|f| c.at(5).map(|a| f.replace("$5", a)))
58                .or(c.at(5).map(String::from));
59
60            OS {
61                family: family,
62                major: major,
63                minor: minor,
64                patch: patch,
65                patch_minor: patch_minor,
66            }
67        })
68    }
69}