browscap_rs/
capabilities.rs1use crate::mapper::{MAPPER};
2use crate::{
3 BROWSER, BROWSER_MAJOR_VERSION, BROWSER_TYPE, BrowsCapField, Capabilities, DEVICE_TYPE,
4 PLATFORM, PLATFORM_VERSION, capabilities,
5};
6use hashbrown::HashSet;
7use std::cell::{RefCell};
8use std::hash::Hash;
9use std::sync::{Arc, OnceLock};
10use ustr::Ustr;
11
12pub const UNKNOWN_BROWSCAP_VALUE: &'static str = "Unknown";
13
14pub static DEFAULT_CAPABILITIES: OnceLock<Capabilities> = OnceLock::new();
15
16#[derive(Debug)]
17pub struct CapaCache {
18 cache: RefCell<HashSet<Arc<Capabilities>>>,
19}
20
21impl CapaCache {
22 pub fn new() -> CapaCache {
23 CapaCache {
24 cache: RefCell::new(HashSet::new()),
25 }
26 }
27
28 pub fn get_or_insert(&self, capa: Capabilities) -> Arc<Capabilities> {
29 self.cache.borrow_mut().get_or_insert(Arc::new(capa)).clone()
30 }
31}
32
33impl Capabilities {
34 fn new(values: Vec<Ustr>) -> Capabilities {
35 Capabilities { my_values: values }
36 }
37 pub fn get_value(&self, field: &BrowsCapField) -> Option<&str> {
38 let u_str = MAPPER
39 .get()
40 .unwrap()
41 .read()
42 .unwrap()
43 .get_value(&self.my_values, field);
44 return u_str.map(|x| x.as_str());
45 }
46
47 pub fn get_browser(&self) -> Option<&str> {
48 self.get_value(&BROWSER)
49 }
50
51 pub fn get_browser_type(&self) -> Option<&str> {
52 self.get_value(&BROWSER_TYPE)
53 }
54
55 pub fn get_browser_major_version(&self) -> Option<&str> {
56 self.get_value(&BROWSER_MAJOR_VERSION)
57 }
58
59 pub fn get_platform(&self) -> Option<&str> {
60 self.get_value(&PLATFORM)
61 }
62
63 pub fn get_platform_version(&self) -> Option<&str> {
64 self.get_value(&PLATFORM_VERSION)
65 }
66
67 pub fn get_device_type(&self) -> Option<&str> {
68 self.get_value(&DEVICE_TYPE)
69 }
70}
71
72impl Hash for Capabilities {
73 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
74 for value in self.my_values.iter() {
75 value.hash(state);
76 }
77 }
78}
79impl Eq for Capabilities {}
80
81impl PartialEq for Capabilities {
82 fn eq(&self, other: &Self) -> bool {
83 self.my_values == other.my_values
84 }
85}
86
87pub fn init_default_capa<'a>(fields: &Vec<&'static BrowsCapField>) -> &'a Capabilities {
88 DEFAULT_CAPABILITIES.get_or_init(|| {
89 let mut result: Vec<Ustr> = Vec::new();
90 for _i in 0..fields.len() {
91 result.push(Ustr::from(capabilities::UNKNOWN_BROWSCAP_VALUE));
92 }
93 Capabilities::new(result)
94 })
95}
96
97pub fn get_capabilities(values: Vec<Ustr>, capa_cache: &CapaCache) -> Arc<Capabilities> {
101 let capabilities: Capabilities = Capabilities::new(values);
102 capa_cache.get_or_insert(capabilities)
103}
104
105pub fn init_wild_card_capa<'a>(fields: &'a Vec<&'static BrowsCapField>) -> Arc<Capabilities> {
106 let mut values = init_default_capa(fields).my_values.clone();
107 let mapper = MAPPER.get().unwrap().read().unwrap();
108 for (index, item) in values.iter_mut().enumerate() {
109 let position_field = mapper.position_field(index);
110 if let Some(field) = position_field {
111 if *field == BROWSER || *field == BROWSER_TYPE {
112 *item = Ustr::from("Default Browser");
113 continue;
114 }
115 if field.is_default {
116 *item = Ustr::from(capabilities::UNKNOWN_BROWSCAP_VALUE);
117 }
118 }
119 }
120 Arc::new(Capabilities::new(values))
121}