From 3939741a06b40d449c59a22351edac154e02fdbf Mon Sep 17 00:00:00 2001 From: Tunglies Date: Sat, 30 Aug 2025 02:24:47 +0800 Subject: [PATCH] refactor: migrate from serde_yaml to serde_yaml_ng for improved YAML handling (#4568) * refactor: migrate from serde_yaml to serde_yaml_ng for improved YAML handling * refactor: format code for better readability in DNS configuration --- renovate.json | 2 +- src-tauri/Cargo.lock | 15 ++++++++++++++- src-tauri/Cargo.toml | 3 ++- src-tauri/src/cmd/clash.rs | 17 +++++++++-------- src-tauri/src/cmd/network.rs | 2 +- src-tauri/src/cmd/profile.rs | 2 +- src-tauri/src/cmd/runtime.rs | 4 ++-- src-tauri/src/config/clash.rs | 2 +- src-tauri/src/config/prfitem.rs | 4 ++-- src-tauri/src/config/profiles.rs | 2 +- src-tauri/src/config/runtime.rs | 2 +- src-tauri/src/core/backup.rs | 4 ++-- src-tauri/src/core/core.rs | 2 +- src-tauri/src/enhance/chain.rs | 2 +- src-tauri/src/enhance/field.rs | 2 +- src-tauri/src/enhance/merge.rs | 8 ++++---- src-tauri/src/enhance/mod.rs | 6 ++++-- src-tauri/src/enhance/script.rs | 6 +++--- src-tauri/src/enhance/seq.rs | 6 +++--- src-tauri/src/enhance/tun.rs | 2 +- src-tauri/src/feat/clash.rs | 2 +- src-tauri/src/feat/config.rs | 2 +- src-tauri/src/utils/help.rs | 8 ++++---- src-tauri/src/utils/init.rs | 15 +++++++++------ 24 files changed, 70 insertions(+), 50 deletions(-) diff --git a/renovate.json b/renovate.json index 1fbaebc0..5f7bc309 100644 --- a/renovate.json +++ b/renovate.json @@ -38,5 +38,5 @@ } ], "postUpdateOptions": ["pnpmDedupe"], - "ignoreDeps": ["serde_yaml", "criterion"] + "ignoreDeps": ["criterion"] } diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index f3269d48..98a250ff 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1127,7 +1127,7 @@ dependencies = [ "scopeguard", "serde", "serde_json", - "serde_yaml", + "serde_yaml_ng", "sha2 0.10.9", "sys-locale", "sysinfo", @@ -6455,6 +6455,19 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "serde_yaml_ng" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4db627b98b36d4203a7b458cf3573730f2bb591b28871d916dfa9efabfd41f" +dependencies = [ + "indexmap 2.11.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + [[package]] name = "serialize-to-javascript" version = "0.1.2" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 43195d23..c4b80ffa 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -28,7 +28,7 @@ chrono = "0.4.41" sysinfo = { version = "0.37.0", features = ["network", "system"] } boa_engine = "0.20.0" serde_json = "1.0.143" -serde_yaml = "0.9.34" +serde_yaml_ng = "0.10.0" once_cell = "1.21.3" port_scanner = "0.1.5" delay_timer = "0.11.6" @@ -83,6 +83,7 @@ isahc = { version = "1.7.2", default-features = false, features = [ "parking_lot", ] } + [target.'cfg(windows)'.dependencies] runas = "=1.2.0" deelevate = "0.2.0" diff --git a/src-tauri/src/cmd/clash.rs b/src-tauri/src/cmd/clash.rs index 01b34105..aec8b60c 100644 --- a/src-tauri/src/cmd/clash.rs +++ b/src-tauri/src/cmd/clash.rs @@ -12,7 +12,7 @@ use crate::{ utils::logging::Type, wrap_err, }; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; use std::time::Duration; const CONFIG_REFRESH_INTERVAL: Duration = Duration::from_secs(60); @@ -143,7 +143,7 @@ pub async fn test_delay(url: String) -> CmdResult { #[tauri::command] pub async fn save_dns_config(dns_config: Mapping) -> CmdResult { use crate::utils::dirs; - use serde_yaml; + use serde_yaml_ng; use tokio::fs; // 获取DNS配置文件路径 @@ -152,7 +152,7 @@ pub async fn save_dns_config(dns_config: Mapping) -> CmdResult { .join("dns_config.yaml"); // 保存DNS配置到文件 - let yaml_str = serde_yaml::to_string(&dns_config).map_err(|e| e.to_string())?; + let yaml_str = serde_yaml_ng::to_string(&dns_config).map_err(|e| e.to_string())?; fs::write(&dns_path, yaml_str) .await .map_err(|e| e.to_string())?; @@ -187,15 +187,16 @@ pub async fn apply_dns_config(apply: bool) -> CmdResult { })?; // 解析DNS配置 - let patch_config = serde_yaml::from_str::(&dns_yaml).map_err(|e| { - logging!(error, Type::Config, "Failed to parse DNS config: {e}"); - e.to_string() - })?; + let patch_config = + serde_yaml_ng::from_str::(&dns_yaml).map_err(|e| { + logging!(error, Type::Config, "Failed to parse DNS config: {e}"); + e.to_string() + })?; logging!(info, Type::Config, "Applying DNS config from file"); // 创建包含DNS配置的patch - let mut patch = serde_yaml::Mapping::new(); + let mut patch = serde_yaml_ng::Mapping::new(); patch.insert("dns".into(), patch_config.into()); // 应用DNS配置到运行时配置 diff --git a/src-tauri/src/cmd/network.rs b/src-tauri/src/cmd/network.rs index 1b0c14fb..3fbb33ea 100644 --- a/src-tauri/src/cmd/network.rs +++ b/src-tauri/src/cmd/network.rs @@ -3,7 +3,7 @@ use crate::core::{async_proxy_query::AsyncProxyQuery, EventDrivenProxyManager}; use crate::process::AsyncHandler; use crate::wrap_err; use network_interface::NetworkInterface; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; /// get the system proxy #[tauri::command] diff --git a/src-tauri/src/cmd/profile.rs b/src-tauri/src/cmd/profile.rs index d78f6446..0108b419 100644 --- a/src-tauri/src/cmd/profile.rs +++ b/src-tauri/src/cmd/profile.rs @@ -381,7 +381,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { match file_read_result { Ok(Ok(content)) => { let yaml_parse_result = AsyncHandler::spawn_blocking(move || { - serde_yaml::from_str::(&content) + serde_yaml_ng::from_str::(&content) }) .await; diff --git a/src-tauri/src/cmd/runtime.rs b/src-tauri/src/cmd/runtime.rs index a72c095f..434bac92 100644 --- a/src-tauri/src/cmd/runtime.rs +++ b/src-tauri/src/cmd/runtime.rs @@ -1,7 +1,7 @@ use super::CmdResult; use crate::{config::*, wrap_err}; use anyhow::Context; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; use std::collections::HashMap; /// 获取运行时配置 @@ -19,7 +19,7 @@ pub async fn get_runtime_yaml() -> CmdResult { wrap_err!(config .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) .and_then( - |config| serde_yaml::to_string(config).context("failed to convert config to yaml") + |config| serde_yaml_ng::to_string(config).context("failed to convert config to yaml") )) } diff --git a/src-tauri/src/config/clash.rs b/src-tauri/src/config/clash.rs index 1f51c3c9..0342d41b 100644 --- a/src-tauri/src/config/clash.rs +++ b/src-tauri/src/config/clash.rs @@ -3,7 +3,7 @@ use crate::utils::dirs::{ipc_path, path_to_str}; use crate::utils::{dirs, help}; use anyhow::Result; use serde::{Deserialize, Serialize}; -use serde_yaml::{Mapping, Value}; +use serde_yaml_ng::{Mapping, Value}; use std::{ net::{IpAddr, Ipv4Addr, SocketAddr}, str::FromStr, diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs index e3c07d6d..19e1f26b 100644 --- a/src-tauri/src/config/prfitem.rs +++ b/src-tauri/src/config/prfitem.rs @@ -5,7 +5,7 @@ use crate::utils::{ }; use anyhow::{bail, Context, Result}; use serde::{Deserialize, Serialize}; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; use std::{fs, time::Duration}; #[derive(Debug, Clone, Deserialize, Serialize, Default)] @@ -355,7 +355,7 @@ impl PrfItem { let data = data.trim_start_matches('\u{feff}'); // check the data whether the valid yaml format - let yaml = serde_yaml::from_str::(data) + let yaml = serde_yaml_ng::from_str::(data) .context("the remote profile data is invalid yaml")?; if !yaml.contains_key("proxies") && !yaml.contains_key("proxy-providers") { diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index ef557370..3d628c04 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -6,7 +6,7 @@ use crate::{ }; use anyhow::{bail, Context, Result}; use serde::{Deserialize, Serialize}; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; use std::collections::HashSet; use tokio::fs; diff --git a/src-tauri/src/config/runtime.rs b/src-tauri/src/config/runtime.rs index 66b3fec2..03278cc6 100644 --- a/src-tauri/src/config/runtime.rs +++ b/src-tauri/src/config/runtime.rs @@ -1,6 +1,6 @@ use crate::enhance::field::use_keys; use serde::{Deserialize, Serialize}; -use serde_yaml::{Mapping, Value}; +use serde_yaml_ng::{Mapping, Value}; use std::collections::HashMap; #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct IRuntime { diff --git a/src-tauri/src/core/backup.rs b/src-tauri/src/core/backup.rs index 2160fd46..3f9cfba4 100644 --- a/src-tauri/src/core/backup.rs +++ b/src-tauri/src/core/backup.rs @@ -264,14 +264,14 @@ pub fn create_backup() -> Result<(String, PathBuf), Error> { zip.write_all(fs::read(dirs::clash_path()?)?.as_slice())?; let mut verge_config: serde_json::Value = - serde_yaml::from_str(&fs::read_to_string(dirs::verge_path()?)?)?; + serde_yaml_ng::from_str(&fs::read_to_string(dirs::verge_path()?)?)?; if let Some(obj) = verge_config.as_object_mut() { obj.remove("webdav_username"); obj.remove("webdav_password"); obj.remove("webdav_url"); } zip.start_file(dirs::VERGE_CONFIG, options)?; - zip.write_all(serde_yaml::to_string(&verge_config)?.as_bytes())?; + zip.write_all(serde_yaml_ng::to_string(&verge_config)?.as_bytes())?; zip.start_file(dirs::PROFILE_YAML, options)?; zip.write_all(fs::read(dirs::profiles_path()?)?.as_slice())?; diff --git a/src-tauri/src/core/core.rs b/src-tauri/src/core/core.rs index 6afb2076..4b8ad96c 100644 --- a/src-tauri/src/core/core.rs +++ b/src-tauri/src/core/core.rs @@ -317,7 +317,7 @@ impl CoreManager { }; // 对YAML文件尝试解析,只检查语法正确性 logging!(info, Type::Config, true, "进行YAML语法检查"); - match serde_yaml::from_str::(&content) { + match serde_yaml_ng::from_str::(&content) { Ok(_) => { logging!(info, Type::Config, true, "YAML语法检查通过"); Ok((true, String::new())) diff --git a/src-tauri/src/enhance/chain.rs b/src-tauri/src/enhance/chain.rs index ba79107a..9f9b0e8b 100644 --- a/src-tauri/src/enhance/chain.rs +++ b/src-tauri/src/enhance/chain.rs @@ -3,7 +3,7 @@ use crate::{ config::PrfItem, utils::{dirs, help}, }; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; use std::fs; #[derive(Debug, Clone)] diff --git a/src-tauri/src/enhance/field.rs b/src-tauri/src/enhance/field.rs index f58b588c..77dbeced 100644 --- a/src-tauri/src/enhance/field.rs +++ b/src-tauri/src/enhance/field.rs @@ -1,4 +1,4 @@ -use serde_yaml::{Mapping, Value}; +use serde_yaml_ng::{Mapping, Value}; use std::collections::HashSet; pub const HANDLE_FIELDS: [&str; 12] = [ diff --git a/src-tauri/src/enhance/merge.rs b/src-tauri/src/enhance/merge.rs index 1da09dec..4b41ee05 100644 --- a/src-tauri/src/enhance/merge.rs +++ b/src-tauri/src/enhance/merge.rs @@ -1,5 +1,5 @@ use super::use_lowercase; -use serde_yaml::{self, Mapping, Value}; +use serde_yaml_ng::{self, Mapping, Value}; fn deep_merge(a: &mut Value, b: &Value) { match (a, b) { @@ -54,10 +54,10 @@ fn test_merge() -> anyhow::Result<()> { script1: test "; - let merge = serde_yaml::from_str::(merge)?; - let config = serde_yaml::from_str::(config)?; + let merge = serde_yaml_ng::from_str::(merge)?; + let config = serde_yaml_ng::from_str::(config)?; - let _ = serde_yaml::to_string(&use_merge(merge, config))?; + let _ = serde_yaml_ng::to_string(&use_merge(merge, config))?; Ok(()) } diff --git a/src-tauri/src/enhance/mod.rs b/src-tauri/src/enhance/mod.rs index c6bf8ef8..5ad489da 100644 --- a/src-tauri/src/enhance/mod.rs +++ b/src-tauri/src/enhance/mod.rs @@ -7,7 +7,7 @@ mod tun; use self::{chain::*, field::*, merge::*, script::*, seq::*, tun::*}; use crate::{config::Config, utils::tmpl}; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; use std::collections::{HashMap, HashSet}; type ResultLog = Vec<(String, String)>; @@ -386,7 +386,9 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { if dns_path.exists() { if let Ok(dns_yaml) = fs::read_to_string(&dns_path) { - if let Ok(dns_config) = serde_yaml::from_str::(&dns_yaml) { + if let Ok(dns_config) = + serde_yaml_ng::from_str::(&dns_yaml) + { // 处理hosts配置 if let Some(hosts_value) = dns_config.get("hosts") { if hosts_value.is_mapping() { diff --git a/src-tauri/src/enhance/script.rs b/src-tauri/src/enhance/script.rs index ae0e9e8b..1350d3e3 100644 --- a/src-tauri/src/enhance/script.rs +++ b/src-tauri/src/enhance/script.rs @@ -1,6 +1,6 @@ use super::use_lowercase; use anyhow::{Error, Result}; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; pub fn use_script( script: String, @@ -149,11 +149,11 @@ fn test_script() { enable: false "; - let config = serde_yaml::from_str(config).expect("Failed to parse test config YAML"); + let config = serde_yaml_ng::from_str(config).expect("Failed to parse test config YAML"); let (config, results) = use_script(script.into(), config, "".to_string()) .expect("Script execution should succeed in test"); - let _ = serde_yaml::to_string(&config).expect("Failed to serialize config to YAML"); + let _ = serde_yaml_ng::to_string(&config).expect("Failed to serialize config to YAML"); let yaml_config_size = std::mem::size_of_val(&config); let box_yaml_config_size = std::mem::size_of_val(&Box::new(config)); assert!(box_yaml_config_size < yaml_config_size); diff --git a/src-tauri/src/enhance/seq.rs b/src-tauri/src/enhance/seq.rs index 406adfe6..e0061a90 100644 --- a/src-tauri/src/enhance/seq.rs +++ b/src-tauri/src/enhance/seq.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use serde_yaml::{Mapping, Sequence, Value}; +use serde_yaml_ng::{Mapping, Sequence, Value}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct SeqMap { @@ -86,7 +86,7 @@ pub fn use_seq(seq: SeqMap, mut config: Mapping, field: &str) -> Mapping { mod tests { use super::*; #[allow(unused_imports)] - use serde_yaml::Value; + use serde_yaml_ng::Value; #[test] #[allow(clippy::unwrap_used)] @@ -110,7 +110,7 @@ proxy-groups: - "proxy1" "#; let mut config: Mapping = - serde_yaml::from_str(config_str).expect("Failed to parse test config YAML"); + serde_yaml_ng::from_str(config_str).expect("Failed to parse test config YAML"); let seq = SeqMap { prepend: Sequence::new(), diff --git a/src-tauri/src/enhance/tun.rs b/src-tauri/src/enhance/tun.rs index 92f7a5eb..5f81a99f 100644 --- a/src-tauri/src/enhance/tun.rs +++ b/src-tauri/src/enhance/tun.rs @@ -1,4 +1,4 @@ -use serde_yaml::{Mapping, Value}; +use serde_yaml_ng::{Mapping, Value}; #[cfg(target_os = "macos")] use crate::process::AsyncHandler; diff --git a/src-tauri/src/feat/clash.rs b/src-tauri/src/feat/clash.rs index d5aa9e0e..3542f714 100644 --- a/src-tauri/src/feat/clash.rs +++ b/src-tauri/src/feat/clash.rs @@ -6,7 +6,7 @@ use crate::{ process::AsyncHandler, utils::{logging::Type, resolve}, }; -use serde_yaml::{Mapping, Value}; +use serde_yaml_ng::{Mapping, Value}; /// Restart the Clash core pub async fn restart_clash_core() { diff --git a/src-tauri/src/feat/config.rs b/src-tauri/src/feat/config.rs index 3299fc3e..d8a834cc 100644 --- a/src-tauri/src/feat/config.rs +++ b/src-tauri/src/feat/config.rs @@ -6,7 +6,7 @@ use crate::{ utils::logging::Type, }; use anyhow::Result; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; /// Patch Clash configuration pub async fn patch_clash(patch: Mapping) -> Result<()> { diff --git a/src-tauri/src/utils/help.rs b/src-tauri/src/utils/help.rs index 32f64fce..b14b9d0b 100644 --- a/src-tauri/src/utils/help.rs +++ b/src-tauri/src/utils/help.rs @@ -2,7 +2,7 @@ use crate::{enhance::seq::SeqMap, logging, utils::logging::Type}; use anyhow::{anyhow, bail, Context, Result}; use nanoid::nanoid; use serde::{de::DeserializeOwned, Serialize}; -use serde_yaml::Mapping; +use serde_yaml_ng::Mapping; use std::{path::PathBuf, str::FromStr}; /// read data from yaml as struct T @@ -13,7 +13,7 @@ pub async fn read_yaml(path: &PathBuf) -> Result { let yaml_str = tokio::fs::read_to_string(path).await?; - Ok(serde_yaml::from_str::(&yaml_str)?) + Ok(serde_yaml_ng::from_str::(&yaml_str)?) } /// read mapping from yaml @@ -27,7 +27,7 @@ pub async fn read_mapping(path: &PathBuf) -> Result { .with_context(|| format!("failed to read the file \"{}\"", path.display()))?; // YAML语法检查 - match serde_yaml::from_str::(&yaml_str) { + match serde_yaml_ng::from_str::(&yaml_str) { Ok(mut val) => { val.apply_merge() .with_context(|| format!("failed to apply merge \"{}\"", path.display()))?; @@ -66,7 +66,7 @@ pub async fn save_yaml( data: &T, prefix: Option<&str>, ) -> Result<()> { - let data_str = serde_yaml::to_string(data)?; + let data_str = serde_yaml_ng::to_string(data)?; let yaml_str = match prefix { Some(prefix) => format!("{prefix}\n\n{data_str}"), diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs index d43a1c3a..8f64b36f 100644 --- a/src-tauri/src/utils/init.rs +++ b/src-tauri/src/utils/init.rs @@ -142,10 +142,10 @@ pub async fn delete_log() -> Result<()> { /// 初始化DNS配置文件 async fn init_dns_config() -> Result<()> { - use serde_yaml::Value; + use serde_yaml_ng::Value; // 创建DNS子配置 - let dns_config = serde_yaml::Mapping::from_iter([ + let dns_config = serde_yaml_ng::Mapping::from_iter([ ("enable".into(), Value::Bool(true)), ("listen".into(), Value::String(":53".into())), ("enhanced-mode".into(), Value::String("fake-ip".into())), @@ -197,7 +197,7 @@ async fn init_dns_config() -> Result<()> { ("fallback".into(), Value::Sequence(vec![])), ( "nameserver-policy".into(), - Value::Mapping(serde_yaml::Mapping::new()), + Value::Mapping(serde_yaml_ng::Mapping::new()), ), ( "proxy-server-nameserver".into(), @@ -211,7 +211,7 @@ async fn init_dns_config() -> Result<()> { ("direct-nameserver-follow-policy".into(), Value::Bool(false)), ( "fallback-filter".into(), - Value::Mapping(serde_yaml::Mapping::from_iter([ + Value::Mapping(serde_yaml_ng::Mapping::from_iter([ ("geoip".into(), Value::Bool(true)), ("geoip-code".into(), Value::String("CN".into())), ( @@ -234,9 +234,12 @@ async fn init_dns_config() -> Result<()> { ]); // 获取默认DNS和host配置 - let default_dns_config = serde_yaml::Mapping::from_iter([ + let default_dns_config = serde_yaml_ng::Mapping::from_iter([ ("dns".into(), Value::Mapping(dns_config)), - ("hosts".into(), Value::Mapping(serde_yaml::Mapping::new())), + ( + "hosts".into(), + Value::Mapping(serde_yaml_ng::Mapping::new()), + ), ]); // 检查DNS配置文件是否存在