1use yaml_rust::{Yaml};
2use yaml;
3use regex::Regex;
4
5
6#[derive(Debug, PartialEq, Eq)]
8pub struct UserAgent {
9 pub family: String,
10 pub major: Option<String>,
11 pub minor: Option<String>,
12 pub patch: Option<String>,
13}
14
15#[derive(Debug)]
16pub struct UserAgentParser {
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}
23
24impl UserAgentParser {
25 pub fn from_yaml(y: &Yaml) -> Option<UserAgentParser> {
26 yaml::string_from_map(y, "regex")
27 .map(|r| r.replace(r"\-", r"-"))
28 .map(|r| r.replace(r"\ ", r" "))
29 .map(|r| r.replace(r"\/", r"/"))
30 .and_then(|r| Regex::new(&r[..]).ok())
31 .map(|r| UserAgentParser {
32 regex: r,
33 family: yaml::string_from_map(y, "family_replacement"),
34 major: yaml::string_from_map(y, "v1_replacement"),
35 minor: yaml::string_from_map(y, "v2_replacement"),
36 patch: yaml::string_from_map(y, "v3_replacement"),
37 })
38 }
39
40 pub fn parse(&self, agent: String) -> Option<UserAgent> {
41 self.regex.captures(&agent[..]).map(|c| {
42 let family = self.family.clone()
43 .and_then(|f| c.at(1).map(|a| f.replace("$1", a)))
44 .unwrap_or(c.at(1).unwrap_or("Other").to_string());
45 let major = self.major.clone()
46 .and_then(|f| c.at(2).map(|a| f.replace("$2", a)))
47 .or(c.at(2).map(String::from));
48 let minor = self.minor.clone()
49 .and_then(|f| c.at(3).map(|a| f.replace("$3", a)))
50 .or(c.at(3).map(String::from));
51 let patch = self.patch.clone()
52 .and_then(|f| c.at(4).map(|a| f.replace("$4", a)))
53 .or(c.at(4).map(String::from));
54
55 UserAgent {
56 family: family,
57 major: major,
58 minor: minor,
59 patch: patch,
60 }
61 })
62 }
63}