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, rename = "chrome-android")]
pub chrome_android: T,
#[serde(default, rename = "firefox-android")]
pub firerfox_android: T,
#[serde(default, rename = "opera-android")]
pub opera_android: T,
#[serde(default)]
pub quest: T,
#[serde(default, rename = "react-native")]
pub react_native: 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,
}
impl<T> BrowserData<T>
where
T: Default,
{
pub fn insert(&mut self, k: &str, v: T) -> T {
for (key, value) in self.iter_mut() {
if k == key {
return std::mem::replace(value, v);
}
}
panic!("unknown key: {}", k)
}
}
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)
}
}