mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-27 16:22:11 +08:00
* refactor(config): unify YAML persistence * refactor(config): remove redundant config APIs * refactor(config): remove unused config APIs * refactor(config): narrow profile APIs * fix(config): preserve profiles on invalid reorder * refactor(startup): narrow resolve helpers * refactor(config): unify mixed port defaults * refactor(network): simplify response APIs * refactor(config): make profile builders infallible * refactor(config): make profile activation infallible * refactor(api): simplify internal runtime APIs * refactor: consolidate internal config and window APIs
86 lines
2.9 KiB
Rust
86 lines
2.9 KiB
Rust
use serde_yaml_ng::{Mapping, Value};
|
|
use smartstring::alias::String;
|
|
use std::collections::{HashMap, HashSet};
|
|
|
|
use crate::enhance::field::use_keys;
|
|
|
|
const PATCH_CONFIG_INNER: [&str; 5] = ["allow-lan", "ipv6", "log-level", "unified-delay", "tunnels"];
|
|
|
|
#[derive(Default, Clone)]
|
|
pub struct IRuntime {
|
|
pub config: Option<Mapping>,
|
|
// Keys seen in the profile pipeline, including merge and script output.
|
|
pub exists_keys: HashSet<String>,
|
|
// TODO 或许可以用 FixMap 来存储以提升效率
|
|
pub chain_logs: HashMap<String, Vec<(String, String)>>,
|
|
}
|
|
|
|
impl IRuntime {
|
|
#[inline]
|
|
pub fn patch_config(&mut self, patch: &Mapping) {
|
|
let config = if let Some(config) = self.config.as_mut() {
|
|
config
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
for key in PATCH_CONFIG_INNER.iter() {
|
|
if let Some(value) = patch.get(key) {
|
|
config.insert((*key).into(), value.clone());
|
|
}
|
|
}
|
|
|
|
let Some(patch_tun) = patch.get("tun") else {
|
|
return;
|
|
};
|
|
|
|
let tun_key = Value::from("tun");
|
|
if !matches!(config.get(&tun_key), Some(Value::Mapping(_))) {
|
|
config.insert(tun_key.clone(), Value::Mapping(Mapping::new()));
|
|
}
|
|
|
|
if let (Some(patch_tun_mapping), Some(Value::Mapping(tun))) = (patch_tun.as_mapping(), config.get_mut(&tun_key))
|
|
{
|
|
for key in use_keys(patch_tun_mapping) {
|
|
if let Some(value) = patch_tun_mapping.get(key.as_str()) {
|
|
tun.insert(Value::from(key.as_str()), value.clone());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Rebuilds `dialer-proxy` links from an ordered proxy chain, or removes them for `None`.
|
|
#[inline]
|
|
pub fn update_proxy_chain_config(&mut self, proxy_chain_config: Option<Value>) {
|
|
let config = if let Some(config) = self.config.as_mut() {
|
|
config
|
|
} else {
|
|
return;
|
|
};
|
|
|
|
if let Some(Value::Sequence(proxies)) = config.get_mut("proxies") {
|
|
proxies.iter_mut().for_each(|proxy| {
|
|
if let Some(proxy) = proxy.as_mapping_mut()
|
|
&& proxy.get("dialer-proxy").is_some()
|
|
{
|
|
proxy.remove("dialer-proxy");
|
|
}
|
|
});
|
|
}
|
|
|
|
if let Some(Value::Sequence(dialer_proxies)) = proxy_chain_config
|
|
&& let Some(Value::Sequence(proxies)) = config.get_mut("proxies")
|
|
{
|
|
for (i, dialer_proxy) in dialer_proxies.iter().enumerate() {
|
|
if let Some(Value::Mapping(proxy)) =
|
|
proxies.iter_mut().find(|proxy| proxy.get("name") == Some(dialer_proxy))
|
|
&& i != 0
|
|
&& let Some(dialer_proxy) = dialer_proxies.get(i - 1)
|
|
{
|
|
proxy.insert("dialer-proxy".into(), dialer_proxy.to_owned());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|