uap_rust/
parser.rs

1use std::io::prelude::*;
2use std::fs::{File};
3use yaml_rust::{YamlLoader};
4
5use client::{Client};
6use ua::{UserAgent, UserAgentParser};
7use device::{Device, DeviceParser};
8use os::{OS, OSParser};
9use result::*;
10use yaml;
11
12///The `Parser` type, used for parsing user agent strings into `Client` structs.
13#[derive(Debug)]
14pub struct Parser {
15    pub ua_regex: Vec<UserAgentParser>,
16    pub devices_regex: Vec<DeviceParser>,
17    pub os_regex: Vec<OSParser>,
18}
19
20impl Parser {
21
22    ///Constructs a `Parser` from a file path to a regexes file.
23    ///
24    ///See [uap-core](https://github.com/ua-parser/uap-core/) documentation for information on the
25    ///file format.
26    pub fn from_file(regexes_file: &str) -> Result<Parser> {
27        let mut file = try!(File::open(regexes_file));
28        let mut yaml = String::new();
29        let _ = file.read_to_string(&mut yaml);
30        Parser::from_str(&yaml)
31    }
32
33    ///Constructs a `Parser` from an str containing regexes.
34    ///
35    ///See [uap-core](https://github.com/ua-parser/uap-core/) documentation for information on the
36    ///format.
37    pub fn from_str(s: &str) -> Result<Parser> {
38        //Parse the yaml.
39        let docs = try!(YamlLoader::load_from_str(&s));
40        let p = Parser {
41            devices_regex: yaml::from_map(&docs[0],"device_parsers")
42                .map(|y| yaml::filter_map_over_arr(y, DeviceParser::from_yaml)).unwrap(),
43            ua_regex: yaml::from_map(&docs[0],"user_agent_parsers")
44                .map(|y| yaml::filter_map_over_arr(y, UserAgentParser::from_yaml)).unwrap(),
45            os_regex: yaml::from_map(&docs[0],"os_parsers")
46                .map(|y| yaml::filter_map_over_arr(y, OSParser::from_yaml)).unwrap(),
47        };
48        Ok(p)
49    }
50
51    ///Constructs a `Parser` from the staticly complied regexes file data.
52    ///
53    ///See [uap-core](https://github.com/ua-parser/uap-core/) documentation for information on the
54    ///format.
55    pub fn new() -> Result<Parser> {
56        let s = include_str!("uap-core/regexes.yaml");
57        Parser::from_str(&s)
58    }
59
60    ///Parses a user agent string into a `Client` struct.
61    pub fn parse(&self, agent: String) -> Client {
62        //For each of the attributes, we find the first regex that matches and use that. Otherwise
63        //we use a default value.
64
65        let ua = self.ua_regex.iter().filter_map(|u| u.parse(agent.clone())).next();
66        let u = ua.unwrap_or(
67            UserAgent {
68                family: "Other".to_string(),
69                major: None,
70                minor: None,
71                patch: None,
72            });
73        let dev = self.devices_regex.iter().filter_map(|d| d.parse(agent.clone())).next();
74        let d = dev.unwrap_or(Device {
75            family: "Other".to_string(),
76            model: None,
77            brand: None,
78            regex: None,
79        });
80        let oss = self.os_regex.iter().filter_map(|d| d.parse(agent.clone())).next();
81        let o = oss.unwrap_or(OS {
82            family: "Other".to_string(),
83            major: None,
84            minor: None,
85            patch: None,
86            patch_minor: None,
87        });
88        Client {
89            user_agent: u,
90            os: o,
91            device: d,
92        }
93    }
94}