use crate::models::cron::{CronTaskConfig, CronTaskConfigs};
use crate::models::proxy_group_config::{ProxyGroupConfig, ProxyGroupConfigs, ProxyGroupType};
use crate::models::regex_match_config::{RegexMatchConfig, RegexMatchConfigs};
use crate::models::ruleset::{RulesetConfig, RulesetConfigs};
use crate::utils::string::starts_with;
fn parse_group_times(src: &str, interval: &mut u32, timeout: &mut u32, tolerance: &mut u32) {
let parts: Vec<&str> = src.split(',').collect();
if parts.len() >= 1 {
if let Ok(val) = parts[0].parse::<u32>() {
*interval = val;
}
}
if parts.len() >= 2 {
if let Ok(val) = parts[1].parse::<u32>() {
*timeout = val;
}
}
if parts.len() >= 3 {
if let Ok(val) = parts[2].parse::<u32>() {
*tolerance = val;
}
}
}
pub trait FromIni<T> {
fn from_ini(arr: &[String]) -> T;
}
pub trait FromIniWithDelimiter<T> {
fn from_ini_with_delimiter(arr: &[String], delimiter: &str) -> T;
}
impl FromIni<ProxyGroupConfigs> for ProxyGroupConfigs {
fn from_ini(arr: &[String]) -> ProxyGroupConfigs {
let mut confs = Vec::new();
for x in arr {
let mut rules_upper_bound;
let mut conf = ProxyGroupConfig::default();
let v_array: Vec<&str> = x.split('`').collect();
if v_array.len() < 3 {
continue;
}
conf.name = v_array[0].to_string();
let type_str = v_array[1];
rules_upper_bound = v_array.len();
conf.group_type = match type_str {
"select" => ProxyGroupType::Select,
"relay" => ProxyGroupType::Relay,
"url-test" => ProxyGroupType::URLTest,
"fallback" => ProxyGroupType::Fallback,
"load-balance" => ProxyGroupType::LoadBalance,
"ssid" => ProxyGroupType::SSID,
"smart" => ProxyGroupType::Smart,
_ => ProxyGroupType::Select,
};
if conf.group_type == ProxyGroupType::URLTest
|| conf.group_type == ProxyGroupType::LoadBalance
|| conf.group_type == ProxyGroupType::Fallback
{
if rules_upper_bound < 5 {
continue;
}
rules_upper_bound -= 2;
conf.url = v_array[rules_upper_bound].to_string();
let mut interval = 0;
let mut timeout = 5;
let mut tolerance = 0;
parse_group_times(
v_array[rules_upper_bound + 1],
&mut interval,
&mut timeout,
&mut tolerance,
);
conf.interval = interval;
conf.timeout = timeout;
conf.tolerance = tolerance;
}
for i in 2..rules_upper_bound {
if starts_with(v_array[i], "!!PROVIDER=") {
let provider_list: Vec<&str> = v_array[i][11..].split(',').collect();
for provider in provider_list {
conf.using_provider.push(provider.to_string());
}
} else {
conf.proxies.push(v_array[i].to_string());
}
}
confs.push(conf);
}
confs
}
}
impl FromIni<Vec<RulesetConfig>> for RulesetConfigs {
fn from_ini(arr: &[String]) -> Vec<RulesetConfig> {
let mut confs = Vec::new();
for x in arr {
let mut conf = RulesetConfig::default();
let pos = x.find(',');
if pos.is_none() {
continue;
}
let pos = pos.unwrap();
conf.group = x[..pos].to_string();
if x.len() > pos + 3 && &x[pos + 1..pos + 3] == "[]" {
conf.url = x[pos + 1..].to_string();
confs.push(conf);
continue;
}
let epos = x.rfind(',');
if pos != epos.unwrap_or(pos) {
let epos = epos.unwrap();
if let Ok(interval) = x[epos + 1..].parse::<u32>() {
conf.interval = interval;
}
conf.url = x[pos + 1..epos].to_string();
} else {
conf.url = x[pos + 1..].to_string();
}
confs.push(conf);
}
confs
}
}
impl FromIniWithDelimiter<RegexMatchConfigs> for RegexMatchConfigs {
fn from_ini_with_delimiter(arr: &[String], delimiter: &str) -> RegexMatchConfigs {
let mut confs = Vec::new();
for x in arr {
let mut conf = RegexMatchConfig::new(String::new(), String::new(), String::new());
if starts_with(x, "script:") {
conf.script = x[7..].to_string();
confs.push(conf);
continue;
}
let pos = x.rfind(delimiter);
conf._match = x[..pos.unwrap_or(x.len())].to_string();
if let Some(p) = pos {
if p < x.len() - 1 {
conf.replace = x[p + delimiter.len()..].to_string();
}
}
conf.compile();
confs.push(conf);
}
confs
}
}
impl FromIni<CronTaskConfigs> for CronTaskConfigs {
fn from_ini(arr: &[String]) -> CronTaskConfigs {
let mut confs = Vec::new();
for x in arr {
let mut conf = CronTaskConfig::default();
let v_array: Vec<&str> = x.split('`').collect();
if v_array.len() < 3 {
continue;
}
conf.name = v_array[0].to_string();
conf.cron_exp = v_array[1].to_string();
conf.path = v_array[2].to_string();
if v_array.len() > 3 {
if let Ok(timeout) = v_array[3].parse::<u32>() {
conf.timeout = timeout;
}
}
confs.push(conf);
}
confs
}
}