1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use anyhow::Error;
use serde::{Deserialize, Serialize};
use st_map::StaticMap;
use self::version::Version;
pub mod query;
pub mod version;
#[derive(Debug, Default, Deserialize, Clone, Copy, Serialize, StaticMap, PartialEq, Eq)]
#[serde(deny_unknown_fields)]
pub struct BrowserData<T: Default> {
#[serde(default)]
pub chrome: T,
#[serde(default)]
pub and_chr: T,
#[serde(default)]
pub and_ff: T,
#[serde(default)]
pub op_mob: T,
#[serde(default)]
pub ie: T,
#[serde(default)]
pub edge: T,
#[serde(default)]
pub firefox: T,
#[serde(default)]
pub safari: T,
#[serde(default)]
pub node: T,
#[serde(default)]
pub ios: T,
#[serde(default)]
pub samsung: T,
#[serde(default)]
pub opera: T,
#[serde(default)]
pub android: T,
#[serde(default)]
pub electron: T,
#[serde(default)]
pub phantom: T,
#[serde(default)]
pub opera_mobile: T,
#[serde(default)]
pub rhino: T,
#[serde(default)]
pub deno: T,
#[serde(default)]
pub hermes: T,
#[serde(default)]
pub oculus: T,
#[serde(default)]
pub bun: T,
}
pub type Versions = BrowserData<Option<Version>>;
impl BrowserData<Option<Version>> {
pub fn is_any_target(&self) -> bool {
self.iter().all(|(_, v)| v.is_none())
}
pub fn parse_versions(distribs: Vec<browserslist::Distrib>) -> Result<Self, Error> {
fn remap(key: &str) -> &str {
match key {
"and_chr" => "chrome",
"and_ff" => "firefox",
"ie_mob" => "ie",
"ios_saf" => "ios",
"op_mob" => "opera",
_ => key,
}
}
let mut data: Versions = BrowserData::default();
for dist in distribs {
let browser = dist.name();
let browser = remap(browser);
let version = dist.version();
match browser {
"and_qq" | "and_uc" | "baidu" | "bb" | "kaios" | "op_mini" => continue,
_ => {}
}
let version = version
.split_once('-')
.map(|(version, _)| version)
.unwrap_or(version)
.parse()
.ok();
let version = match version {
Some(v) => v,
None => continue,
};
if data[&browser].map(|v| v > version).unwrap_or(true) {
for (k, v) in data.iter_mut() {
if browser == k {
*v = Some(version);
}
}
}
}
Ok(data)
}
}