diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 122808f61..6a96fb611 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -1131,6 +1131,7 @@ dependencies = [ "serde_json", "serde_yaml_ng", "sha2 0.10.9", + "smartstring", "sys-locale", "sysinfo", "sysproxy", @@ -6780,6 +6781,18 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "smartstring" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" +dependencies = [ + "autocfg", + "serde", + "static_assertions", + "version_check", +] + [[package]] name = "smol" version = "1.3.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index f3fa64411..b91641166 100755 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -87,6 +87,7 @@ tauri-plugin-devtools = { version = "2.0.1" } tauri-plugin-mihomo = { git = "https://github.com/clash-verge-rev/tauri-plugin-mihomo" } clash_verge_logger = { version = "0.1.0", git = "https://github.com/clash-verge-rev/clash-verge-logger" } async-trait = "0.1.89" +smartstring = { version = "1.0.1", features = ["serde"] } clash_verge_service_ipc = { version = "2.0.17", features = [ "client", ], git = "https://github.com/clash-verge-rev/clash-verge-service-ipc" } diff --git a/src-tauri/src/cmd/app.rs b/src-tauri/src/cmd/app.rs index d91f83321..4daa150f7 100644 --- a/src-tauri/src/cmd/app.rs +++ b/src-tauri/src/cmd/app.rs @@ -1,12 +1,14 @@ use super::CmdResult; +use crate::core::sysopt::Sysopt; use crate::{ + cmd::StringifyErr, feat, logging, utils::{ dirs::{self, PathBufExec}, logging::Type, }, - wrap_err, }; +use smartstring::alias::String; use std::path::Path; use tauri::{AppHandle, Manager}; use tokio::fs; @@ -14,29 +16,29 @@ use tokio::fs; /// 打开应用程序所在目录 #[tauri::command] pub async fn open_app_dir() -> CmdResult<()> { - let app_dir = wrap_err!(dirs::app_home_dir())?; - wrap_err!(open::that(app_dir)) + let app_dir = dirs::app_home_dir().stringify_err()?; + open::that(app_dir).stringify_err() } /// 打开核心所在目录 #[tauri::command] pub async fn open_core_dir() -> CmdResult<()> { - let core_dir = wrap_err!(tauri::utils::platform::current_exe())?; + let core_dir = tauri::utils::platform::current_exe().stringify_err()?; let core_dir = core_dir.parent().ok_or("failed to get core dir")?; - wrap_err!(open::that(core_dir)) + open::that(core_dir).stringify_err() } /// 打开日志目录 #[tauri::command] pub async fn open_logs_dir() -> CmdResult<()> { - let log_dir = wrap_err!(dirs::app_logs_dir())?; - wrap_err!(open::that(log_dir)) + let log_dir = dirs::app_logs_dir().stringify_err()?; + open::that(log_dir).stringify_err() } /// 打开网页链接 #[tauri::command] pub fn open_web_url(url: String) -> CmdResult<()> { - wrap_err!(open::that(url)) + open::that(url.as_str()).stringify_err() } /// 打开/关闭开发者工具 @@ -73,22 +75,27 @@ pub fn get_portable_flag() -> CmdResult { /// 获取应用目录 #[tauri::command] pub fn get_app_dir() -> CmdResult { - let app_home_dir = wrap_err!(dirs::app_home_dir())?.to_string_lossy().into(); + let app_home_dir = dirs::app_home_dir() + .stringify_err()? + .to_string_lossy() + .into(); Ok(app_home_dir) } /// 获取当前自启动状态 #[tauri::command] pub fn get_auto_launch_status() -> CmdResult { - use crate::core::sysopt::Sysopt; - wrap_err!(Sysopt::global().get_launch_status()) + Sysopt::global().get_launch_status().stringify_err() } /// 下载图标缓存 #[tauri::command] pub async fn download_icon_cache(url: String, name: String) -> CmdResult { - let icon_cache_dir = wrap_err!(dirs::app_home_dir())?.join("icons").join("cache"); - let icon_path = icon_cache_dir.join(&name); + let icon_cache_dir = dirs::app_home_dir() + .stringify_err()? + .join("icons") + .join("cache"); + let icon_path = icon_cache_dir.join(name.as_str()); if icon_path.exists() { return Ok(icon_path.to_string_lossy().into()); @@ -98,9 +105,9 @@ pub async fn download_icon_cache(url: String, name: String) -> CmdResult let _ = std::fs::create_dir_all(&icon_cache_dir); } - let temp_path = icon_cache_dir.join(format!("{}.downloading", &name)); + let temp_path = icon_cache_dir.join(format!("{}.downloading", name.as_str())); - let response = wrap_err!(reqwest::get(&url).await)?; + let response = reqwest::get(url.as_str()).await.stringify_err()?; let content_type = response .headers() @@ -110,7 +117,7 @@ pub async fn download_icon_cache(url: String, name: String) -> CmdResult let is_image = content_type.starts_with("image/"); - let content = wrap_err!(response.bytes().await)?; + let content = response.bytes().await.stringify_err()?; let is_html = content.len() > 15 && (content.starts_with(b" CmdResult } }; - wrap_err!(std::io::copy(&mut content.as_ref(), &mut file))?; + std::io::copy(&mut content.as_ref(), &mut file).stringify_err()?; } if !icon_path.exists() { @@ -149,7 +156,7 @@ pub async fn download_icon_cache(url: String, name: String) -> CmdResult Ok(icon_path.to_string_lossy().into()) } else { let _ = temp_path.remove_if_exists().await; - Err(format!("下载的内容不是有效图片: {url}")) + Err(format!("下载的内容不是有效图片: {}", url.as_str()).into()) } } @@ -163,9 +170,9 @@ pub struct IconInfo { /// 复制图标文件 #[tauri::command] pub async fn copy_icon_file(path: String, icon_info: IconInfo) -> CmdResult { - let file_path = Path::new(&path); + let file_path = Path::new(path.as_str()); - let icon_dir = wrap_err!(dirs::app_home_dir())?.join("icons"); + let icon_dir = dirs::app_home_dir().stringify_err()?.join("icons"); if !icon_dir.exists() { let _ = fs::create_dir_all(&icon_dir).await; } @@ -176,17 +183,26 @@ pub async fn copy_icon_file(path: String, icon_info: IconInfo) -> CmdResult CmdResult Ok(dest_path.to_string_lossy().into()), - Err(err) => Err(err.to_string()), + Err(err) => Err(err.to_string().into()), } } else { Err("file not found".into()) @@ -218,7 +234,7 @@ pub fn notify_ui_ready() -> CmdResult<()> { /// UI加载阶段 #[tauri::command] pub fn update_ui_stage(stage: String) -> CmdResult<()> { - log::info!(target: "app", "UI加载阶段更新: {stage}"); + log::info!(target: "app", "UI加载阶段更新: {}", stage.as_str()); use crate::utils::resolve::ui::UiReadyStage; @@ -229,8 +245,8 @@ pub fn update_ui_stage(stage: String) -> CmdResult<()> { "ResourcesLoaded" => UiReadyStage::ResourcesLoaded, "Ready" => UiReadyStage::Ready, _ => { - log::warn!(target: "app", "未知的UI加载阶段: {stage}"); - return Err(format!("未知的UI加载阶段: {stage}")); + log::warn!(target: "app", "未知的UI加载阶段: {}", stage.as_str()); + return Err(format!("未知的UI加载阶段: {}", stage.as_str()).into()); } }; diff --git a/src-tauri/src/cmd/backup.rs b/src-tauri/src/cmd/backup.rs index d44120c70..8610b682e 100644 --- a/src-tauri/src/cmd/backup.rs +++ b/src-tauri/src/cmd/backup.rs @@ -1,33 +1,34 @@ use super::CmdResult; -use crate::{feat, wrap_err}; +use crate::{cmd::StringifyErr, feat}; use feat::LocalBackupFile; +use smartstring::alias::String; /// Create a local backup #[tauri::command] pub async fn create_local_backup() -> CmdResult<()> { - wrap_err!(feat::create_local_backup().await) + feat::create_local_backup().await.stringify_err() } /// List local backups #[tauri::command] pub fn list_local_backup() -> CmdResult> { - wrap_err!(feat::list_local_backup()) + feat::list_local_backup().stringify_err() } /// Delete local backup #[tauri::command] pub async fn delete_local_backup(filename: String) -> CmdResult<()> { - wrap_err!(feat::delete_local_backup(filename).await) + feat::delete_local_backup(filename).await.stringify_err() } /// Restore local backup #[tauri::command] pub async fn restore_local_backup(filename: String) -> CmdResult<()> { - wrap_err!(feat::restore_local_backup(filename).await) + feat::restore_local_backup(filename).await.stringify_err() } /// Export local backup to a user selected destination #[tauri::command] pub fn export_local_backup(filename: String, destination: String) -> CmdResult<()> { - wrap_err!(feat::export_local_backup(filename, destination)) + feat::export_local_backup(filename, destination).stringify_err() } diff --git a/src-tauri/src/cmd/clash.rs b/src-tauri/src/cmd/clash.rs index 91b4eab7b..09f5e1018 100644 --- a/src-tauri/src/cmd/clash.rs +++ b/src-tauri/src/cmd/clash.rs @@ -6,9 +6,10 @@ use crate::{ config::Config, core::{CoreManager, handle, validate::CoreConfigValidator}, }; -use crate::{config::*, feat, logging, utils::logging::Type, wrap_err}; +use crate::{config::*, feat, logging, utils::logging::Type}; use compact_str::CompactString; use serde_yaml_ng::Mapping; +use smartstring::alias::String; /// 复制Clash环境变量 #[tauri::command] @@ -26,7 +27,7 @@ pub async fn get_clash_info() -> CmdResult { /// 修改Clash配置 #[tauri::command] pub async fn patch_clash_config(payload: Mapping) -> CmdResult { - wrap_err!(feat::patch_clash(payload).await) + feat::patch_clash(payload).await.stringify_err() } /// 修改Clash模式 @@ -54,22 +55,23 @@ pub async fn change_clash_core(clash_core: String) -> CmdResult> Type::Core, "core changed and restarted to {clash_core}" ); - handle::Handle::notice_message("config_core::change_success", &clash_core); + handle::Handle::notice_message("config_core::change_success", clash_core); handle::Handle::refresh_clash(); Ok(None) } Err(err) => { - let error_msg = format!("Core changed but failed to restart: {err}"); + let error_msg: String = + format!("Core changed but failed to restart: {err}").into(); + handle::Handle::notice_message("config_core::change_error", error_msg.clone()); logging!(error, Type::Core, "{error_msg}"); - handle::Handle::notice_message("config_core::change_error", &error_msg); Ok(Some(error_msg)) } } } Err(err) => { - let error_msg = err; + let error_msg: String = err; logging!(error, Type::Core, "failed to change core: {error_msg}"); - handle::Handle::notice_message("config_core::change_error", &error_msg); + handle::Handle::notice_message("config_core::change_error", error_msg.clone()); Ok(Some(error_msg)) } } @@ -78,7 +80,7 @@ pub async fn change_clash_core(clash_core: String) -> CmdResult> /// 启动核心 #[tauri::command] pub async fn start_core() -> CmdResult { - let result = wrap_err!(CoreManager::global().start_core().await); + let result = CoreManager::global().start_core().await.stringify_err(); if result.is_ok() { handle::Handle::refresh_clash(); } @@ -88,7 +90,7 @@ pub async fn start_core() -> CmdResult { /// 关闭核心 #[tauri::command] pub async fn stop_core() -> CmdResult { - let result = wrap_err!(CoreManager::global().stop_core().await); + let result = CoreManager::global().stop_core().await.stringify_err(); if result.is_ok() { handle::Handle::refresh_clash(); } @@ -98,7 +100,7 @@ pub async fn stop_core() -> CmdResult { /// 重启核心 #[tauri::command] pub async fn restart_core() -> CmdResult { - let result = wrap_err!(CoreManager::global().restart_core().await); + let result = CoreManager::global().restart_core().await.stringify_err(); if result.is_ok() { handle::Handle::refresh_clash(); } @@ -250,7 +252,7 @@ pub async fn get_dns_config_content() -> CmdResult { return Err("DNS config file not found".into()); } - let content = fs::read_to_string(&dns_path).await.stringify_err()?; + let content = fs::read_to_string(&dns_path).await.stringify_err()?.into(); Ok(content) } diff --git a/src-tauri/src/cmd/mod.rs b/src-tauri/src/cmd/mod.rs index 7af3b596b..6c7486873 100644 --- a/src-tauri/src/cmd/mod.rs +++ b/src-tauri/src/cmd/mod.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use smartstring::alias::String; pub type CmdResult = Result; @@ -47,7 +48,7 @@ pub trait StringifyErr { impl StringifyErr for Result { fn stringify_err(self) -> CmdResult { - self.map_err(|e| e.to_string()) + self.map_err(|e| e.to_string().into()) } fn stringify_err_log(self, log_fn: F) -> CmdResult @@ -55,7 +56,7 @@ impl StringifyErr for Result { F: Fn(&str), { self.map_err(|e| { - let msg = e.to_string(); + let msg = String::from(e.to_string()); log_fn(&msg); msg }) diff --git a/src-tauri/src/cmd/network.rs b/src-tauri/src/cmd/network.rs index 86ce8ed70..120bd1f02 100644 --- a/src-tauri/src/cmd/network.rs +++ b/src-tauri/src/cmd/network.rs @@ -1,7 +1,7 @@ use super::CmdResult; +use crate::cmd::StringifyErr; use crate::core::{EventDrivenProxyManager, async_proxy_query::AsyncProxyQuery}; use crate::process::AsyncHandler; -use crate::wrap_err; use network_interface::NetworkInterface; use serde_yaml_ng::Mapping; @@ -82,7 +82,7 @@ pub fn get_network_interfaces_info() -> CmdResult> { use network_interface::{NetworkInterface, NetworkInterfaceConfig}; let names = get_network_interfaces(); - let interfaces = wrap_err!(NetworkInterface::show())?; + let interfaces = NetworkInterface::show().stringify_err()?; let mut result = Vec::new(); diff --git a/src-tauri/src/cmd/profile.rs b/src-tauri/src/cmd/profile.rs index 06f9fade3..766cea739 100644 --- a/src-tauri/src/cmd/profile.rs +++ b/src-tauri/src/cmd/profile.rs @@ -1,6 +1,6 @@ use super::CmdResult; +use super::StringifyErr; use crate::{ - cmd::StringifyErr, config::{ Config, IProfiles, PrfItem, PrfOption, profiles::{ @@ -14,8 +14,8 @@ use crate::{ process::AsyncHandler, ret_err, utils::{dirs, help, logging::Type}, - wrap_err, }; +use smartstring::alias::String; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; use std::time::Duration; @@ -86,7 +86,7 @@ pub async fn enhance_profiles() -> CmdResult { Ok(_) => {} Err(e) => { log::error!(target: "app", "{}", e); - return Err(e.to_string()); + return Err(e.to_string().into()); } } handle::Handle::refresh_clash(); @@ -95,7 +95,7 @@ pub async fn enhance_profiles() -> CmdResult { /// 导入配置文件 #[tauri::command] -pub async fn import_profile(url: String, option: Option) -> CmdResult { +pub async fn import_profile(url: std::string::String, option: Option) -> CmdResult { logging!(info, Type::Cmd, "[导入订阅] 开始导入: {}", url); // 直接依赖 PrfItem::from_url 自身的超时/重试逻辑,不再使用 tokio::time::timeout 包裹 @@ -106,7 +106,7 @@ pub async fn import_profile(url: String, option: Option) -> CmdResult } Err(e) => { logging!(error, Type::Cmd, "[导入订阅] 下载失败: {}", e); - return Err(format!("导入订阅失败: {}", e)); + return Err(format!("导入订阅失败: {}", e).into()); } }; @@ -121,7 +121,7 @@ pub async fn import_profile(url: String, option: Option) -> CmdResult }, Err(e) => { logging!(error, Type::Cmd, "[导入订阅] 保存配置失败: {}", e); - return Err(format!("导入订阅失败: {}", e)); + return Err(format!("导入订阅失败: {}", e).into()); } } // 立即发送配置变更通知 @@ -152,7 +152,7 @@ pub async fn reorder_profile(active_id: String, over_id: String) -> CmdResult { } Err(err) => { log::error!(target: "app", "重新排序配置文件失败: {}", err); - Err(format!("重新排序配置文件失败: {}", err)) + Err(format!("重新排序配置文件失败: {}", err).into()) } } } @@ -172,7 +172,7 @@ pub async fn create_profile(item: PrfItem, file_data: Option) -> CmdResu } Err(err) => match err.to_string().as_str() { "the file already exists" => Err("the file already exists".into()), - _ => Err(format!("add profile error: {err}")), + _ => Err(format!("add profile error: {err}").into()), }, } } @@ -184,7 +184,7 @@ pub async fn update_profile(index: String, option: Option) -> CmdResu Ok(_) => Ok(()), Err(e) => { log::error!(target: "app", "{}", e); - Err(e.to_string()) + Err(e.to_string().into()) } } } @@ -194,7 +194,9 @@ pub async fn update_profile(index: String, option: Option) -> CmdResu pub async fn delete_profile(index: String) -> CmdResult { println!("delete_profile: {}", index); // 使用Send-safe helper函数 - let should_update = wrap_err!(profiles_delete_item_safe(index.clone()).await)?; + let should_update = profiles_delete_item_safe(index.clone()) + .await + .stringify_err()?; profiles_save_file_safe().await.stringify_err()?; if should_update { @@ -207,7 +209,7 @@ pub async fn delete_profile(index: String) -> CmdResult { } Err(e) => { log::error!(target: "app", "{}", e); - return Err(e.to_string()); + return Err(e.to_string().into()); } } } @@ -264,7 +266,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { match profiles_data.get_item(new_profile) { Ok(item) => { if let Some(file) = &item.file { - let path = dirs::app_profiles_dir().map(|dir| dir.join(file)); + let path = dirs::app_profiles_dir().map(|dir| dir.join(file.as_str())); path.ok() } else { None @@ -321,7 +323,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { ); handle::Handle::notice_message( "config_validate::yaml_syntax_error", - &error_msg, + error_msg.clone(), ); return Ok(false); } @@ -330,7 +332,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { logging!(error, Type::Cmd, "{}", error_msg); handle::Handle::notice_message( "config_validate::yaml_parse_error", - &error_msg, + error_msg.clone(), ); return Ok(false); } @@ -339,7 +341,10 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { Ok(Err(err)) => { let error_msg = format!("无法读取目标配置文件: {err}"); logging!(error, Type::Cmd, "{}", error_msg); - handle::Handle::notice_message("config_validate::file_read_error", &error_msg); + handle::Handle::notice_message( + "config_validate::file_read_error", + error_msg.clone(), + ); return Ok(false); } Err(_) => { @@ -347,7 +352,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { logging!(error, Type::Cmd, "{}", error_msg); handle::Handle::notice_message( "config_validate::file_read_timeout", - &error_msg, + error_msg.clone(), ); return Ok(false); } @@ -479,12 +484,11 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { items: None, }; // 静默恢复,不触发验证 - wrap_err!({ - Config::profiles() - .await - .draft_mut() - .patch_config(restore_profiles) - })?; + Config::profiles() + .await + .draft_mut() + .patch_config(restore_profiles) + .stringify_err()?; Config::profiles().await.apply(); crate::process::AsyncHandler::spawn(|| async move { @@ -497,7 +501,7 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { } // 发送验证错误通知 - handle::Handle::notice_message("config_validate::error", &error_msg); + handle::Handle::notice_message("config_validate::error", error_msg.to_string()); CURRENT_SWITCHING_PROFILE.store(false, Ordering::SeqCst); Ok(false) } @@ -539,12 +543,11 @@ pub async fn patch_profiles_config(profiles: IProfiles) -> CmdResult { current: Some(prev_profile), items: None, }; - wrap_err!({ - Config::profiles() - .await - .draft_mut() - .patch_config(restore_profiles) - })?; + Config::profiles() + .await + .draft_mut() + .patch_config(restore_profiles) + .stringify_err()?; Config::profiles().await.apply(); } @@ -585,7 +588,9 @@ pub async fn patch_profile(index: String, profile: PrfItem) -> CmdResult { false }; - wrap_err!(profiles_patch_item_safe(index.clone(), profile).await)?; + profiles_patch_item_safe(index.clone(), profile) + .await + .stringify_err()?; // 如果更新间隔或允许自动更新变更,异步刷新定时器 if should_refresh_timer { @@ -609,19 +614,21 @@ pub async fn patch_profile(index: String, profile: PrfItem) -> CmdResult { pub async fn view_profile(index: String) -> CmdResult { let profiles = Config::profiles().await; let profiles_ref = profiles.latest_ref(); - let file = { - wrap_err!(profiles_ref.get_item(&index))? - .file - .clone() - .ok_or("the file field is null") - }?; + let file = profiles_ref + .get_item(&index) + .stringify_err()? + .file + .clone() + .ok_or("the file field is null")?; - let path = wrap_err!(dirs::app_profiles_dir())?.join(file); + let path = dirs::app_profiles_dir() + .stringify_err()? + .join(file.as_str()); if !path.exists() { ret_err!("the file not found"); } - wrap_err!(help::open_file(path)) + help::open_file(path).stringify_err() } /// 读取配置文件内容 @@ -629,8 +636,8 @@ pub async fn view_profile(index: String) -> CmdResult { pub async fn read_profile_file(index: String) -> CmdResult { let profiles = Config::profiles().await; let profiles_ref = profiles.latest_ref(); - let item = wrap_err!(profiles_ref.get_item(&index))?; - let data = wrap_err!(item.read_file())?; + let item = profiles_ref.get_item(&index).stringify_err()?; + let data = item.read_file().stringify_err()?; Ok(data) } diff --git a/src-tauri/src/cmd/proxy.rs b/src-tauri/src/cmd/proxy.rs index a5b34cf46..6f94f729c 100644 --- a/src-tauri/src/cmd/proxy.rs +++ b/src-tauri/src/cmd/proxy.rs @@ -14,7 +14,7 @@ pub async fn sync_tray_proxy_selection() -> CmdResult<()> { } Err(e) => { logging!(error, Type::Cmd, "Failed to sync tray proxy selection: {e}"); - Err(e.to_string()) + Err(e.to_string().into()) } } } diff --git a/src-tauri/src/cmd/runtime.rs b/src-tauri/src/cmd/runtime.rs index 8e335b578..a45f65979 100644 --- a/src-tauri/src/cmd/runtime.rs +++ b/src-tauri/src/cmd/runtime.rs @@ -1,7 +1,8 @@ use super::CmdResult; -use crate::{config::*, core::CoreManager, log_err, wrap_err}; +use crate::{cmd::StringifyErr, config::*, core::CoreManager, log_err}; use anyhow::Context; use serde_yaml_ng::Mapping; +use smartstring::alias::String; use std::collections::HashMap; /// 获取运行时配置 @@ -17,12 +18,14 @@ pub async fn get_runtime_yaml() -> CmdResult { let runtime = runtime.latest_ref(); let config = runtime.config.as_ref(); - wrap_err!( - config - .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) - .and_then(|config| serde_yaml_ng::to_string(config) - .context("failed to convert config to yaml")) - ) + config + .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) + .and_then(|config| { + serde_yaml_ng::to_string(config) + .context("failed to convert config to yaml") + .map(|s| s.into()) + }) + .stringify_err() } /// 获取运行时存在的键 @@ -42,12 +45,11 @@ pub async fn get_runtime_proxy_chain_config(proxy_chain_exit_node: String) -> Cm let runtime = Config::runtime().await; let runtime = runtime.latest_ref(); - let config = wrap_err!( - runtime - .config - .as_ref() - .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) - )?; + let config = runtime + .config + .as_ref() + .ok_or(anyhow::anyhow!("failed to parse config to yaml file")) + .stringify_err()?; if let Some(serde_yaml_ng::Value::Sequence(proxies)) = config.get("proxies") { let mut proxy_name = Some(Some(proxy_chain_exit_node.as_str())); @@ -78,13 +80,14 @@ pub async fn get_runtime_proxy_chain_config(proxy_chain_exit_node: String) -> Cm let mut config: HashMap> = HashMap::new(); - config.insert("proxies".to_string(), proxies_chain); + config.insert("proxies".into(), proxies_chain); - wrap_err!(serde_yaml_ng::to_string(&config).context("YAML generation failed")) + serde_yaml_ng::to_string(&config) + .context("YAML generation failed") + .map(|s| s.into()) + .stringify_err() } else { - wrap_err!(Err(anyhow::anyhow!( - "failed to get proxies or proxy-groups".to_string() - ))) + Err("failed to get proxies or proxy-groups".into()) } } @@ -102,7 +105,9 @@ pub async fn update_proxy_chain_config_in_runtime( } // 生成新的运行配置文件并通知 Clash 核心重新加载 - let run_path = wrap_err!(Config::generate_file(ConfigType::Run).await)?; + let run_path = Config::generate_file(ConfigType::Run) + .await + .stringify_err()?; log_err!(CoreManager::global().put_configs_force(run_path).await); Ok(()) diff --git a/src-tauri/src/cmd/save_profile.rs b/src-tauri/src/cmd/save_profile.rs index 92edda9bc..a1cd34740 100644 --- a/src-tauri/src/cmd/save_profile.rs +++ b/src-tauri/src/cmd/save_profile.rs @@ -1,11 +1,12 @@ use super::CmdResult; use crate::{ + cmd::StringifyErr, config::*, core::{validate::CoreConfigValidator, *}, logging, utils::{dirs, logging::Type}, - wrap_err, }; +use smartstring::alias::String; use tokio::fs; /// 保存profiles的配置 @@ -19,18 +20,18 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR let (file_path, original_content, is_merge_file) = { let profiles = Config::profiles().await; let profiles_guard = profiles.latest_ref(); - let item = wrap_err!(profiles_guard.get_item(&index))?; + let item = profiles_guard.get_item(&index).stringify_err()?; // 确定是否为merge类型文件 let is_merge = item.itype.as_ref().is_some_and(|t| t == "merge"); - let content = wrap_err!(item.read_file())?; + let content = item.read_file().stringify_err()?; let path = item.file.clone().ok_or("file field is null")?; - let profiles_dir = wrap_err!(dirs::app_profiles_dir())?; - (profiles_dir.join(path), content, is_merge) + let profiles_dir = dirs::app_profiles_dir().stringify_err()?; + (profiles_dir.join(path.as_str()), content, is_merge) }; // 保存新的配置文件 let file_data = file_data.ok_or("file_data is None")?; - wrap_err!(fs::write(&file_path, &file_data).await)?; + fs::write(&file_path, &file_data).await.stringify_err()?; let file_path_str = file_path.to_string_lossy().to_string(); logging!( @@ -76,7 +77,9 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR error_msg ); // 恢复原始配置文件 - wrap_err!(fs::write(&file_path, original_content).await)?; + fs::write(&file_path, original_content) + .await + .stringify_err()?; // 发送合并文件专用错误通知 let result = (false, error_msg.clone()); crate::cmd::validate::handle_yaml_validation_notice(&result, "合并配置文件"); @@ -85,8 +88,10 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR Err(e) => { logging!(error, Type::Config, "[cmd配置save] 验证过程发生错误: {}", e); // 恢复原始配置文件 - wrap_err!(fs::write(&file_path, original_content).await)?; - return Err(e.to_string()); + fs::write(&file_path, original_content) + .await + .stringify_err()?; + return Err(e.to_string().into()); } } } @@ -100,7 +105,9 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR Ok((false, error_msg)) => { logging!(warn, Type::Config, "[cmd配置save] 验证失败: {}", error_msg); // 恢复原始配置文件 - wrap_err!(fs::write(&file_path, original_content).await)?; + fs::write(&file_path, original_content) + .await + .stringify_err()?; // 智能判断错误类型 let is_script_error = file_path_str.ends_with(".js") @@ -136,7 +143,7 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR Type::Config, "[cmd配置save] 其他类型验证失败,发送一般通知" ); - handle::Handle::notice_message("config_validate::error", &error_msg); + handle::Handle::notice_message("config_validate::error", error_msg.to_owned()); } Ok(()) @@ -144,8 +151,10 @@ pub async fn save_profile_file(index: String, file_data: Option) -> CmdR Err(e) => { logging!(error, Type::Config, "[cmd配置save] 验证过程发生错误: {}", e); // 恢复原始配置文件 - wrap_err!(fs::write(&file_path, original_content).await)?; - Err(e.to_string()) + fs::write(&file_path, original_content) + .await + .stringify_err()?; + Err(e.to_string().into()) } } } diff --git a/src-tauri/src/cmd/service.rs b/src-tauri/src/cmd/service.rs index 01abdc814..5231ea902 100644 --- a/src-tauri/src/cmd/service.rs +++ b/src-tauri/src/cmd/service.rs @@ -1,4 +1,4 @@ -use super::CmdResult; +use super::{CmdResult, StringifyErr}; use crate::{ core::service::{self, SERVICE_MANAGER, ServiceStatus}, utils::i18n::t, @@ -12,7 +12,7 @@ async fn execute_service_operation_sync(status: ServiceStatus, op_type: &str) -> .await { let emsg = format!("{} Service failed: {}", op_type, e); - return Err(t(emsg.as_str()).await); + return Err(t(emsg.as_str()).await.into()); } Ok(()) } @@ -39,8 +39,6 @@ pub async fn repair_service() -> CmdResult { #[tauri::command] pub async fn is_service_available() -> CmdResult { - service::is_service_available() - .await - .map(|_| true) - .map_err(|e| e.to_string()) + service::is_service_available().await.stringify_err()?; + Ok(true) } diff --git a/src-tauri/src/cmd/uwp.rs b/src-tauri/src/cmd/uwp.rs index dc2eb1201..0f073bf93 100644 --- a/src-tauri/src/cmd/uwp.rs +++ b/src-tauri/src/cmd/uwp.rs @@ -1,13 +1,14 @@ -use super::CmdResult; +use crate::cmd::CmdResult; /// Platform-specific implementation for UWP functionality #[cfg(windows)] mod platform { - use super::CmdResult; - use crate::{core::win_uwp, wrap_err}; + use crate::cmd::CmdResult; + use crate::cmd::StringifyErr; + use crate::core::win_uwp; pub fn invoke_uwp_tool() -> CmdResult { - wrap_err!(win_uwp::invoke_uwptools()) + win_uwp::invoke_uwptools().stringify_err() } } diff --git a/src-tauri/src/cmd/validate.rs b/src-tauri/src/cmd/validate.rs index 23d93b42d..33536e3b7 100644 --- a/src-tauri/src/cmd/validate.rs +++ b/src-tauri/src/cmd/validate.rs @@ -4,11 +4,12 @@ use crate::{ logging, utils::logging::Type, }; +use smartstring::alias::String; /// 发送脚本验证通知消息 #[tauri::command] pub async fn script_validate_notice(status: String, msg: String) -> CmdResult { - handle::Handle::notice_message(&status, &msg); + handle::Handle::notice_message(status.as_str(), msg.as_str()); Ok(()) } @@ -33,7 +34,7 @@ pub fn handle_script_validation_notice(result: &(bool, String), file_type: &str) }; logging!(warn, Type::Config, "{} 验证失败: {}", file_type, error_msg); - handle::Handle::notice_message(status, error_msg); + handle::Handle::notice_message(status, error_msg.to_owned()); } } @@ -117,6 +118,6 @@ pub fn handle_yaml_validation_notice(result: &(bool, String), file_type: &str) { status, error_msg ); - handle::Handle::notice_message(status, error_msg); + handle::Handle::notice_message(status, error_msg.to_owned()); } } diff --git a/src-tauri/src/cmd/verge.rs b/src-tauri/src/cmd/verge.rs index 04f8a6519..eb74339fd 100644 --- a/src-tauri/src/cmd/verge.rs +++ b/src-tauri/src/cmd/verge.rs @@ -1,5 +1,5 @@ use super::CmdResult; -use crate::{config::*, feat, wrap_err}; +use crate::{cmd::StringifyErr, config::*, feat}; /// 获取Verge配置 #[tauri::command] @@ -16,5 +16,5 @@ pub async fn get_verge_config() -> CmdResult { /// 修改Verge配置 #[tauri::command] pub async fn patch_verge_config(payload: IVerge) -> CmdResult { - wrap_err!(feat::patch_verge(payload, false).await) + feat::patch_verge(payload, false).await.stringify_err() } diff --git a/src-tauri/src/cmd/webdav.rs b/src-tauri/src/cmd/webdav.rs index 7375ea5db..6c27868db 100644 --- a/src-tauri/src/cmd/webdav.rs +++ b/src-tauri/src/cmd/webdav.rs @@ -1,6 +1,7 @@ use super::CmdResult; -use crate::{config::*, core, feat, wrap_err}; +use crate::{cmd::StringifyErr, config::*, core, feat}; use reqwest_dav::list_cmd::ListFile; +use smartstring::alias::String; /// 保存 WebDAV 配置 #[tauri::command] @@ -30,23 +31,25 @@ pub async fn save_webdav_config(url: String, username: String, password: String) /// 创建 WebDAV 备份并上传 #[tauri::command] pub async fn create_webdav_backup() -> CmdResult<()> { - wrap_err!(feat::create_backup_and_upload_webdav().await) + feat::create_backup_and_upload_webdav() + .await + .stringify_err() } /// 列出 WebDAV 上的备份文件 #[tauri::command] pub async fn list_webdav_backup() -> CmdResult> { - wrap_err!(feat::list_wevdav_backup().await) + feat::list_wevdav_backup().await.stringify_err() } /// 删除 WebDAV 上的备份文件 #[tauri::command] pub async fn delete_webdav_backup(filename: String) -> CmdResult<()> { - wrap_err!(feat::delete_webdav_backup(filename).await) + feat::delete_webdav_backup(filename).await.stringify_err() } /// 从 WebDAV 恢复备份文件 #[tauri::command] pub async fn restore_webdav_backup(filename: String) -> CmdResult<()> { - wrap_err!(feat::restore_webdav_backup(filename).await) + feat::restore_webdav_backup(filename).await.stringify_err() } diff --git a/src-tauri/src/config/config.rs b/src-tauri/src/config/config.rs index 811371293..4f50443d2 100644 --- a/src-tauri/src/config/config.rs +++ b/src-tauri/src/config/config.rs @@ -8,6 +8,7 @@ use crate::{ }; use anyhow::{Result, anyhow}; use backoff::{Error as BackoffError, ExponentialBackoff}; +use smartstring::alias::String; use std::path::PathBuf; use tokio::sync::OnceCell; use tokio::time::sleep; @@ -122,7 +123,7 @@ impl Config { if let Some((msg_type, msg_content)) = validation_result { sleep(timing::STARTUP_ERROR_DELAY).await; - handle::Handle::notice_message(msg_type, &msg_content); + handle::Handle::notice_message(msg_type, msg_content); } Ok(()) diff --git a/src-tauri/src/config/prfitem.rs b/src-tauri/src/config/prfitem.rs index bb9ff7a6a..6888ee3c4 100644 --- a/src-tauri/src/config/prfitem.rs +++ b/src-tauri/src/config/prfitem.rs @@ -6,6 +6,7 @@ use crate::utils::{ use anyhow::{Context, Result, bail}; use serde::{Deserialize, Serialize}; use serde_yaml_ng::Mapping; +use smartstring::alias::String; use std::{fs, time::Duration}; #[derive(Debug, Clone, Deserialize, Serialize, Default)] @@ -179,8 +180,8 @@ impl PrfItem { file_data: Option, option: Option, ) -> Result { - let uid = help::get_uid("L"); - let file = format!("{uid}.yaml"); + let uid = help::get_uid("L").into(); + let file = format!("{uid}.yaml").into(); let opt_ref = option.as_ref(); let update_interval = opt_ref.and_then(|o| o.update_interval); let mut merge = opt_ref.and_then(|o| o.merge.clone()); @@ -352,9 +353,9 @@ impl PrfItem { None => None, }; - let uid = help::get_uid("R"); - let file = format!("{uid}.yaml"); - let name = name.unwrap_or(filename.unwrap_or("Remote File".into())); + let uid = help::get_uid("R").into(); + let file = format!("{uid}.yaml").into(); + let name = name.unwrap_or(filename.unwrap_or("Remote File".into()).into()); let data = resp.text_with_charset()?; // process the charset "UTF-8 with BOM" @@ -422,13 +423,13 @@ impl PrfItem { /// ## Merge type (enhance) /// create the enhanced item by using `merge` rule pub fn from_merge(uid: Option) -> Result { - let mut id = help::get_uid("m"); + let mut id = help::get_uid("m").into(); let mut template = tmpl::ITEM_MERGE_EMPTY.into(); if let Some(uid) = uid { id = uid; template = tmpl::ITEM_MERGE.into(); } - let file = format!("{id}.yaml"); + let file = format!("{id}.yaml").into(); Ok(PrfItem { uid: Some(id), @@ -449,11 +450,11 @@ impl PrfItem { /// ## Script type (enhance) /// create the enhanced item by using javascript quick.js pub fn from_script(uid: Option) -> Result { - let mut id = help::get_uid("s"); + let mut id = help::get_uid("s").into(); if let Some(uid) = uid { id = uid; } - let file = format!("{id}.js"); // js ext + let file = format!("{id}.js").into(); // js ext Ok(PrfItem { uid: Some(id), @@ -473,8 +474,8 @@ impl PrfItem { /// ## Rules type (enhance) pub fn from_rules() -> Result { - let uid = help::get_uid("r"); - let file = format!("{uid}.yaml"); // yaml ext + let uid = help::get_uid("r").into(); + let file = format!("{uid}.yaml").into(); // yaml ext Ok(PrfItem { uid: Some(uid), @@ -494,8 +495,8 @@ impl PrfItem { /// ## Proxies type (enhance) pub fn from_proxies() -> Result { - let uid = help::get_uid("p"); - let file = format!("{uid}.yaml"); // yaml ext + let uid = help::get_uid("p").into(); + let file = format!("{uid}.yaml").into(); // yaml ext Ok(PrfItem { uid: Some(uid), @@ -515,8 +516,8 @@ impl PrfItem { /// ## Groups type (enhance) pub fn from_groups() -> Result { - let uid = help::get_uid("g"); - let file = format!("{uid}.yaml"); // yaml ext + let uid = help::get_uid("g").into(); + let file = format!("{uid}.yaml").into(); // yaml ext Ok(PrfItem { uid: Some(uid), @@ -540,8 +541,9 @@ impl PrfItem { .file .clone() .ok_or_else(|| anyhow::anyhow!("could not find the file"))?; - let path = dirs::app_profiles_dir()?.join(file); - fs::read_to_string(path).context("failed to read the file") + let path = dirs::app_profiles_dir()?.join(file.as_str()); + let content = fs::read_to_string(path).context("failed to read the file")?; + Ok(content.into()) } /// save the file data @@ -550,7 +552,7 @@ impl PrfItem { .file .clone() .ok_or_else(|| anyhow::anyhow!("could not find the file"))?; - let path = dirs::app_profiles_dir()?.join(file); + let path = dirs::app_profiles_dir()?.join(file.as_str()); fs::write(path, data.as_bytes()).context("failed to save the file") } } diff --git a/src-tauri/src/config/profiles.rs b/src-tauri/src/config/profiles.rs index 4d2e4f10f..2fef30be5 100644 --- a/src-tauri/src/config/profiles.rs +++ b/src-tauri/src/config/profiles.rs @@ -6,6 +6,7 @@ use crate::utils::{ use anyhow::{Context, Result, bail}; use serde::{Deserialize, Serialize}; use serde_yaml_ng::Mapping; +use smartstring::alias::String; use std::collections::HashSet; use tokio::fs; @@ -47,7 +48,7 @@ impl IProfiles { if let Some(items) = profiles.items.as_mut() { for item in items.iter_mut() { if item.uid.is_none() { - item.uid = Some(help::get_uid("d")); + item.uid = Some(help::get_uid("d").into()); } } } @@ -142,7 +143,7 @@ impl IProfiles { let file = item.file.clone().ok_or_else(|| { anyhow::anyhow!("file field is required when file_data is provided") })?; - let path = dirs::app_profiles_dir()?.join(&file); + let path = dirs::app_profiles_dir()?.join(file.as_str()); fs::write(&path, file_data.as_bytes()) .await @@ -240,13 +241,13 @@ impl IProfiles { // move the field value after save if let Some(file_data) = item.file_data.take() { let file = each.file.take(); - let file = - file.unwrap_or(item.file.take().unwrap_or(format!("{}.yaml", &uid))); + let file = file + .unwrap_or(item.file.take().unwrap_or(format!("{}.yaml", &uid).into())); // the file must exists each.file = Some(file.clone()); - let path = dirs::app_profiles_dir()?.join(&file); + let path = dirs::app_profiles_dir()?.join(file.as_str()); fs::write(&path, file_data.as_bytes()) .await @@ -291,7 +292,7 @@ impl IProfiles { && let Some(file) = items.remove(index).file { let _ = dirs::app_profiles_dir()? - .join(file) + .join(file.as_str()) .remove_if_exists() .await; } @@ -306,7 +307,7 @@ impl IProfiles { && let Some(file) = items.remove(index).file { let _ = dirs::app_profiles_dir()? - .join(file) + .join(file.as_str()) .remove_if_exists() .await; } @@ -321,7 +322,7 @@ impl IProfiles { && let Some(file) = items.remove(index).file { let _ = dirs::app_profiles_dir()? - .join(file) + .join(file.as_str()) .remove_if_exists() .await; } @@ -336,7 +337,7 @@ impl IProfiles { && let Some(file) = items.remove(index).file { let _ = dirs::app_profiles_dir()? - .join(file) + .join(file.as_str()) .remove_if_exists() .await; } @@ -351,7 +352,7 @@ impl IProfiles { && let Some(file) = items.remove(index).file { let _ = dirs::app_profiles_dir()? - .join(file) + .join(file.as_str()) .remove_if_exists() .await; } @@ -366,7 +367,7 @@ impl IProfiles { && let Some(file) = items.remove(index).file { let _ = dirs::app_profiles_dir()? - .join(file) + .join(file.as_str()) .remove_if_exists() .await; } @@ -392,7 +393,7 @@ impl IProfiles { (Some(current), Some(items)) => { if let Some(item) = items.iter().find(|e| e.uid.as_ref() == Some(current)) { let file_path = match item.file.as_ref() { - Some(file) => dirs::app_profiles_dir()?.join(file), + Some(file) => dirs::app_profiles_dir()?.join(file.as_str()), None => bail!("failed to get the file field"), }; return help::read_mapping(&file_path).await; @@ -544,7 +545,7 @@ impl IProfiles { log::info!(target: "app", "已清理冗余文件: {file_name}"); } Err(e) => { - failed_deletions.push(format!("{file_name}: {e}")); + failed_deletions.push(format!("{file_name}: {e}").into()); log::warn!(target: "app", "清理文件失败: {file_name} - {e}"); } } diff --git a/src-tauri/src/config/runtime.rs b/src-tauri/src/config/runtime.rs index 7113402b4..db8c96147 100644 --- a/src-tauri/src/config/runtime.rs +++ b/src-tauri/src/config/runtime.rs @@ -1,7 +1,9 @@ use crate::enhance::field::use_keys; use serde::{Deserialize, Serialize}; use serde_yaml_ng::{Mapping, Value}; +use smartstring::alias::String; use std::collections::HashMap; + #[derive(Default, Debug, Clone, Deserialize, Serialize)] pub struct IRuntime { pub config: Option, @@ -30,15 +32,15 @@ impl IRuntime { let patch_tun = patch.get("tun"); if patch_tun.is_some() { let tun = config.get("tun"); - let mut tun = tun.map_or(Mapping::new(), |val| { + let mut tun: Mapping = tun.map_or(Mapping::new(), |val| { val.as_mapping().cloned().unwrap_or(Mapping::new()) }); let patch_tun = patch_tun.map_or(Mapping::new(), |val| { val.as_mapping().cloned().unwrap_or(Mapping::new()) }); use_keys(&patch_tun).into_iter().for_each(|key| { - if let Some(value) = patch_tun.get(&key).to_owned() { - tun.insert(key.into(), value.clone()); + if let Some(value) = patch_tun.get(key.as_str()) { + tun.insert(Value::from(key.as_str()), value.clone()); } }); diff --git a/src-tauri/src/config/verge.rs b/src-tauri/src/config/verge.rs index d522e8a18..c0bad3165 100644 --- a/src-tauri/src/config/verge.rs +++ b/src-tauri/src/config/verge.rs @@ -6,6 +6,7 @@ use crate::{ use anyhow::Result; use log::LevelFilter; use serde::{Deserialize, Serialize}; +use smartstring::alias::String; /// ### `verge.yaml` schema #[derive(Default, Debug, Clone, Deserialize, Serialize)] @@ -322,7 +323,7 @@ impl IVerge { fn get_system_language() -> String { let sys_lang = sys_locale::get_locale() - .unwrap_or_else(|| String::from("en")) + .unwrap_or_else(|| "en".into()) .to_lowercase(); let lang_code = sys_lang.split(['_', '-']).next().unwrap_or("en"); diff --git a/src-tauri/src/core/backup.rs b/src-tauri/src/core/backup.rs index f64a7f4f6..25521e6ef 100644 --- a/src-tauri/src/core/backup.rs +++ b/src-tauri/src/core/backup.rs @@ -3,6 +3,7 @@ use anyhow::Error; use once_cell::sync::OnceCell; use parking_lot::Mutex; use reqwest_dav::list_cmd::{ListEntity, ListFile}; +use smartstring::alias::String; use std::{ collections::HashMap, env::{consts::OS, temp_dir}, @@ -123,8 +124,11 @@ impl WebDavClient { })) .build()?, ) - .set_host(config.url) - .set_auth(reqwest_dav::Auth::Basic(config.username, config.password)) + .set_host(config.url.into()) + .set_auth(reqwest_dav::Auth::Basic( + config.username.into(), + config.password.into(), + )) .build()?; // 尝试检查目录是否存在,如果不存在尝试创建 @@ -163,7 +167,7 @@ impl WebDavClient { pub async fn upload(&self, file_path: PathBuf, file_name: String) -> Result<(), Error> { let client = self.get_client(Operation::Upload).await?; - let webdav_path: String = format!("{}/{}", dirs::BACKUP_DIR, file_name); + let webdav_path: String = format!("{}/{}", dirs::BACKUP_DIR, file_name).into(); // 读取文件并上传,如果失败尝试一次重试 let file_content = fs::read(&file_path)?; @@ -248,8 +252,8 @@ impl WebDavClient { pub fn create_backup() -> Result<(String, PathBuf), Error> { let now = chrono::Local::now().format("%Y-%m-%d_%H-%M-%S").to_string(); - let zip_file_name = format!("{OS}-backup-{now}.zip"); - let zip_path = temp_dir().join(&zip_file_name); + let zip_file_name: String = format!("{OS}-backup-{now}.zip").into(); + let zip_path = temp_dir().join(zip_file_name.as_str()); let file = fs::File::create(&zip_path)?; let mut zip = zip::ZipWriter::new(file); diff --git a/src-tauri/src/core/event_driven_proxy.rs b/src-tauri/src/core/event_driven_proxy.rs index 079e9d8bb..dd0928c76 100644 --- a/src-tauri/src/core/event_driven_proxy.rs +++ b/src-tauri/src/core/event_driven_proxy.rs @@ -8,6 +8,7 @@ use crate::config::{Config, IVerge}; use crate::core::{async_proxy_query::AsyncProxyQuery, handle}; use crate::process::AsyncHandler; use once_cell::sync::Lazy; +use smartstring::alias::String; use sysproxy::{Autoproxy, Sysproxy}; #[derive(Debug, Clone)] @@ -426,13 +427,15 @@ impl EventDrivenProxyManager { }; let port = verge_mixed_port.unwrap_or(default_port); - let host = proxy_host.unwrap_or_else(|| network::DEFAULT_PROXY_HOST.into()); + let host = proxy_host + .unwrap_or_else(|| network::DEFAULT_PROXY_HOST.into()) + .into(); Sysproxy { enable: true, host, port, - bypass: Self::get_bypass_config().await, + bypass: Self::get_bypass_config().await.into(), } } @@ -445,9 +448,9 @@ impl EventDrivenProxyManager { let custom = verge.system_proxy_bypass.as_deref().unwrap_or(""); match (use_default, custom.is_empty()) { - (_, true) => bypass::DEFAULT.to_string(), - (true, false) => format!("{},{}", bypass::DEFAULT, custom), - (false, false) => custom.to_string(), + (_, true) => bypass::DEFAULT.into(), + (true, false) => format!("{},{}", bypass::DEFAULT, custom).into(), + (false, false) => custom.into(), } } diff --git a/src-tauri/src/core/handle.rs b/src-tauri/src/core/handle.rs index 8a1d16a89..ef868f59d 100644 --- a/src-tauri/src/core/handle.rs +++ b/src-tauri/src/core/handle.rs @@ -1,5 +1,6 @@ use crate::{APP_HANDLE, constants::timing, singleton}; use parking_lot::RwLock; +use smartstring::alias::String; use std::{sync::Arc, thread}; use tauri::{AppHandle, Manager, WebviewWindow}; use tauri_plugin_mihomo::{Mihomo, MihomoExt}; @@ -199,7 +200,7 @@ impl Handle { pub fn set_activation_policy(&self, policy: tauri::ActivationPolicy) -> Result<(), String> { Self::app_handle() .set_activation_policy(policy) - .map_err(|e| e.to_string()) + .map_err(|e| e.to_string().into()) } pub fn set_activation_policy_regular(&self) { diff --git a/src-tauri/src/core/hotkey.rs b/src-tauri/src/core/hotkey.rs index f527d4b11..c6c69d271 100755 --- a/src-tauri/src/core/hotkey.rs +++ b/src-tauri/src/core/hotkey.rs @@ -6,6 +6,7 @@ use crate::{ }; use anyhow::{Result, bail}; use parking_lot::Mutex; +use smartstring::alias::String; use std::{collections::HashMap, fmt, str::FromStr, sync::Arc}; use tauri::{AppHandle, Manager}; use tauri_plugin_global_shortcut::{Code, GlobalShortcutExt, ShortcutState}; diff --git a/src-tauri/src/core/manager/config.rs b/src-tauri/src/core/manager/config.rs index bcc7c138a..263ddb4b0 100644 --- a/src-tauri/src/core/manager/config.rs +++ b/src-tauri/src/core/manager/config.rs @@ -7,6 +7,7 @@ use crate::{ utils::{dirs, help, logging::Type}, }; use anyhow::{Result, anyhow}; +use smartstring::alias::String; use std::{path::PathBuf, time::Instant}; use tauri_plugin_mihomo::Error as MihomoError; use tokio::time::sleep; diff --git a/src-tauri/src/core/manager/lifecycle.rs b/src-tauri/src/core/manager/lifecycle.rs index 25b0a2966..4dfbae883 100644 --- a/src-tauri/src/core/manager/lifecycle.rs +++ b/src-tauri/src/core/manager/lifecycle.rs @@ -8,6 +8,7 @@ use crate::{ utils::logging::Type, }; use anyhow::Result; +use smartstring::alias::String; impl CoreManager { pub async fn start_core(&self) -> Result<()> { @@ -48,7 +49,7 @@ impl CoreManager { .ok_or_else(|| "Clash core cannot be None".to_string())?; if !IVerge::VALID_CLASH_CORES.contains(&core.as_str()) { - return Err(format!("Invalid clash core: {}", core)); + return Err(format!("Invalid clash core: {}", core).into()); } Config::verge().await.draft_mut().clash_core = clash_core; @@ -61,7 +62,9 @@ impl CoreManager { .await .map_err(|e| e.to_string())?; - self.apply_config(run_path).await.map_err(|e| e.to_string()) + self.apply_config(run_path) + .await + .map_err(|e| e.to_string().into()) } async fn prepare_startup(&self) -> Result<()> { diff --git a/src-tauri/src/core/manager/state.rs b/src-tauri/src/core/manager/state.rs index 4290b237e..ff01a8c1f 100644 --- a/src-tauri/src/core/manager/state.rs +++ b/src-tauri/src/core/manager/state.rs @@ -37,7 +37,7 @@ impl CoreManager { let (mut rx, child) = app_handle .shell() - .sidecar(&clash_core)? + .sidecar(clash_core.as_str())? .args([ "-d", dirs::path_to_str(&config_dir)?, diff --git a/src-tauri/src/core/notification.rs b/src-tauri/src/core/notification.rs index 1df825d95..08102fc09 100644 --- a/src-tauri/src/core/notification.rs +++ b/src-tauri/src/core/notification.rs @@ -4,6 +4,7 @@ use crate::{ utils::logging::Type, }; use parking_lot::RwLock; +use smartstring::alias::String; use std::{ sync::{ atomic::{AtomicU64, Ordering}, diff --git a/src-tauri/src/core/sysopt.rs b/src-tauri/src/core/sysopt.rs index 0303287b6..958c7cf55 100644 --- a/src-tauri/src/core/sysopt.rs +++ b/src-tauri/src/core/sysopt.rs @@ -7,6 +7,7 @@ use crate::{ utils::logging::Type, }; use anyhow::Result; +use smartstring::alias::String; use std::sync::Arc; #[cfg(not(target_os = "windows"))] use sysproxy::{Autoproxy, Sysproxy}; @@ -45,7 +46,7 @@ async fn get_bypass() -> String { if custom_bypass.is_empty() { DEFAULT_BYPASS.into() } else if use_default { - format!("{DEFAULT_BYPASS},{custom_bypass}") + format!("{DEFAULT_BYPASS},{custom_bypass}").into() } else { custom_bypass } @@ -53,7 +54,7 @@ async fn get_bypass() -> String { // Uses tokio Command with CREATE_NO_WINDOW flag to avoid DLL initialization issues during shutdown #[cfg(target_os = "windows")] -async fn execute_sysproxy_command(args: Vec) -> Result<()> { +async fn execute_sysproxy_command(args: Vec) -> Result<()> { use crate::utils::dirs; use anyhow::bail; #[allow(unused_imports)] // Required for .creation_flags() method @@ -68,7 +69,7 @@ async fn execute_sysproxy_command(args: Vec) -> Result<()> { } let output = Command::new(sysproxy_exe) - .args(&args) + .args(args) .creation_flags(0x08000000) // CREATE_NO_WINDOW - 隐藏窗口 .output() .await?; @@ -132,9 +133,9 @@ impl Sysopt { { let mut sys = Sysproxy { enable: false, - host: proxy_host.clone(), + host: proxy_host.clone().into(), port, - bypass: get_bypass().await, + bypass: get_bypass().await.into(), }; let mut auto = Autoproxy { enable: false, @@ -178,13 +179,13 @@ impl Sysopt { return result; } - let args = if pac_enable { + let args: Vec = if pac_enable { let address = format!("http://{proxy_host}:{pac_port}/commands/pac"); vec!["pac".into(), address] } else { let address = format!("{proxy_host}:{port}"); let bypass = get_bypass().await; - vec!["global".into(), address, bypass] + vec!["global".into(), address, bypass.into()] }; execute_sysproxy_command(args).await?; diff --git a/src-tauri/src/core/timer.rs b/src-tauri/src/core/timer.rs index dee031a7b..29eba1fdb 100644 --- a/src-tauri/src/core/timer.rs +++ b/src-tauri/src/core/timer.rs @@ -2,6 +2,7 @@ use crate::{config::Config, feat, logging, logging_error, singleton, utils::logg use anyhow::{Context, Result}; use delay_timer::prelude::{DelayTimer, DelayTimerBuilder, TaskBuilder}; use parking_lot::RwLock; +use smartstring::alias::String; use std::{ collections::HashMap, pin::Pin, diff --git a/src-tauri/src/core/tray/mod.rs b/src-tauri/src/core/tray/mod.rs index 3be829dbf..abc6cc392 100644 --- a/src-tauri/src/core/tray/mod.rs +++ b/src-tauri/src/core/tray/mod.rs @@ -19,6 +19,7 @@ use super::handle; use anyhow::Result; use futures::future::join_all; use parking_lot::Mutex; +use smartstring::alias::String; use std::collections::HashMap; use std::{ fs, @@ -218,7 +219,7 @@ impl Tray { let app_handle = handle::Handle::app_handle(); let tray_event = { Config::verge().await.latest_ref().tray_event.clone() }; - let tray_event: String = tray_event.unwrap_or("main_window".into()); + let tray_event = tray_event.unwrap_or("main_window".into()); let tray = app_handle .tray_by_id("main") .ok_or_else(|| anyhow::anyhow!("Failed to get main tray"))?; @@ -625,7 +626,7 @@ async fn create_tray_menu( .iter() .filter_map(|group| group.get("name")) .filter_map(|name| name.as_str()) - .map(|name| name.to_string()) + .map(|name| name.into()) .collect::>() }) .unwrap_or_default() @@ -671,7 +672,7 @@ async fn create_tray_menu( let is_current_profile = Config::profiles() .await .data_mut() - .is_current_profile_index(profile_uid.to_string()); + .is_current_profile_index(profile_uid.clone()); CheckMenuItem::with_id( &app_handle, format!("profiles_{profile_uid}"), @@ -780,7 +781,7 @@ async fn create_tray_menu( &group_items_refs, ) { let insertion_index = submenus.len(); - submenus.push((group_name.to_string(), insertion_index, submenu)); + submenus.push((group_name.into(), insertion_index, submenu)); } else { log::warn!(target: "app", "创建代理组子菜单失败: {}", group_name); } diff --git a/src-tauri/src/core/validate.rs b/src-tauri/src/core/validate.rs index a30f53a3d..777d65053 100644 --- a/src-tauri/src/core/validate.rs +++ b/src-tauri/src/core/validate.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use smartstring::alias::String; use std::path::Path; use std::sync::Arc; use tauri_plugin_shell::ShellExt; @@ -124,7 +125,7 @@ impl CoreConfigValidator { let content = match std::fs::read_to_string(config_path) { Ok(content) => content, Err(err) => { - let error_msg = format!("Failed to read file: {err}"); + let error_msg = format!("Failed to read file: {err}").into(); logging!(error, Type::Validate, "无法读取文件: {}", error_msg); return Ok((false, error_msg)); } @@ -138,7 +139,7 @@ impl CoreConfigValidator { } Err(err) => { // 使用标准化的前缀,以便错误处理函数能正确识别 - let error_msg = format!("YAML syntax error: {err}"); + let error_msg = format!("YAML syntax error: {err}").into(); logging!(error, Type::Validate, "YAML语法错误: {}", error_msg); Ok((false, error_msg)) } @@ -151,7 +152,7 @@ impl CoreConfigValidator { let content = match std::fs::read_to_string(path) { Ok(content) => content, Err(err) => { - let error_msg = format!("Failed to read script file: {err}"); + let error_msg = format!("Failed to read script file: {err}").into(); logging!(warn, Type::Validate, "脚本语法错误: {}", err); //handle::Handle::notice_message("config_validate::script_syntax_error", &error_msg); return Ok((false, error_msg)); @@ -184,7 +185,7 @@ impl CoreConfigValidator { Ok((true, String::new())) } Err(err) => { - let error_msg = format!("Script syntax error: {err}"); + let error_msg = format!("Script syntax error: {err}").into(); logging!(warn, Type::Validate, "脚本语法错误: {}", err); //handle::Handle::notice_message("config_validate::script_syntax_error", &error_msg); Ok((false, error_msg)) @@ -205,7 +206,7 @@ impl CoreConfigValidator { // 检查文件是否存在 if !std::path::Path::new(config_path).exists() { - let error_msg = format!("File not found: {config_path}"); + let error_msg = format!("File not found: {config_path}").into(); //handle::Handle::notice_message("config_validate::file_not_found", &error_msg); return Ok((false, error_msg)); } @@ -282,13 +283,13 @@ impl CoreConfigValidator { // 使用子进程运行clash验证配置 let output = app_handle .shell() - .sidecar(clash_core)? + .sidecar(clash_core.as_str())? .args(["-t", "-d", app_dir_str, "-f", config_path]) .output() .await?; - let stderr = String::from_utf8_lossy(&output.stderr); - let stdout = String::from_utf8_lossy(&output.stdout); + let stderr = std::string::String::from_utf8_lossy(&output.stderr); + let stdout = std::string::String::from_utf8_lossy(&output.stdout); // 检查进程退出状态和错误输出 let error_keywords = ["FATA", "fatal", "Parse config error", "level=fatal"]; @@ -314,7 +315,7 @@ impl CoreConfigValidator { }; logging!(info, Type::Validate, "-------- 验证结束 --------"); - Ok((false, error_msg)) // 返回错误消息给调用者处理 + Ok((false, error_msg.into())) // 返回错误消息给调用者处理 } else { logging!(info, Type::Validate, "验证成功"); logging!(info, Type::Validate, "-------- 验证结束 --------"); diff --git a/src-tauri/src/enhance/chain.rs b/src-tauri/src/enhance/chain.rs index e0adb9ceb..fa9341f56 100644 --- a/src-tauri/src/enhance/chain.rs +++ b/src-tauri/src/enhance/chain.rs @@ -4,6 +4,7 @@ use crate::{ utils::{dirs, help}, }; use serde_yaml_ng::Mapping; +use smartstring::alias::String; use std::fs; #[derive(Debug, Clone)] @@ -73,7 +74,7 @@ impl AsyncChainItemFrom for Option { let itype = item.itype.as_ref()?.as_str(); let file = item.file.clone()?; let uid = item.uid.clone().unwrap_or("".into()); - let path = dirs::app_profiles_dir().ok()?.join(file); + let path = dirs::app_profiles_dir().ok()?.join(file.as_str()); if !path.exists() { return None; @@ -82,7 +83,7 @@ impl AsyncChainItemFrom for Option { match itype { "script" => Some(ChainItem { uid, - data: ChainType::Script(fs::read_to_string(path).ok()?), + data: ChainType::Script(fs::read_to_string(path).ok()?.into()), }), "merge" => Some(ChainItem { uid, diff --git a/src-tauri/src/enhance/field.rs b/src-tauri/src/enhance/field.rs index 77dbeced5..b75f682fe 100644 --- a/src-tauri/src/enhance/field.rs +++ b/src-tauri/src/enhance/field.rs @@ -1,4 +1,5 @@ use serde_yaml_ng::{Mapping, Value}; +use smartstring::alias::String; use std::collections::HashSet; pub const HANDLE_FIELDS: [&str; 12] = [ @@ -31,7 +32,7 @@ pub fn use_lowercase(config: Mapping) -> Mapping { if let Some(key_str) = key.as_str() { let mut key_str = String::from(key_str); key_str.make_ascii_lowercase(); - ret.insert(Value::from(key_str), value); + ret.insert(Value::from(key_str.as_str()), value); } } ret @@ -70,8 +71,8 @@ pub fn use_keys(config: &Mapping) -> Vec { config .iter() .filter_map(|(key, _)| key.as_str()) - .map(|s| { - let mut s = s.to_string(); + .map(|s: &str| { + let mut s: String = s.into(); s.make_ascii_lowercase(); s }) diff --git a/src-tauri/src/enhance/mod.rs b/src-tauri/src/enhance/mod.rs index e3dfbfa51..f6ee459e0 100644 --- a/src-tauri/src/enhance/mod.rs +++ b/src-tauri/src/enhance/mod.rs @@ -8,6 +8,7 @@ mod tun; use self::{chain::*, field::*, merge::*, script::*, seq::*, tun::*}; use crate::{config::Config, utils::tmpl}; use serde_yaml_ng::Mapping; +use smartstring::alias::String; use std::collections::{HashMap, HashSet}; type ResultLog = Vec<(String, String)>; @@ -192,7 +193,7 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { let item = { let profiles = Config::profiles().await; let profiles = profiles.latest_ref(); - profiles.get_item(&"Merge".to_string()).ok().cloned() + profiles.get_item(&"Merge".into()).ok().cloned() }; if let Some(item) = item { >::from_async(&item).await @@ -209,7 +210,7 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { let item = { let profiles = Config::profiles().await; let profiles = profiles.latest_ref(); - profiles.get_item(&"Script".to_string()).ok().cloned() + profiles.get_item(&"Script".into()).ok().cloned() }; if let Some(item) = item { >::from_async(&item).await @@ -253,7 +254,7 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { config = res_config; logs.extend(res_logs); } - Err(err) => logs.push(("exception".into(), err.to_string())), + Err(err) => logs.push(("exception".into(), err.to_string().into())), } result_map.insert(global_script.uid, logs); @@ -280,13 +281,13 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { if let ChainType::Script(script) = script_item.data { let mut logs = vec![]; - match use_script(script, config.to_owned(), profile_name.to_owned()) { + match use_script(script, config.to_owned(), profile_name) { Ok((res_config, res_logs)) => { exists_keys.extend(use_keys(&res_config)); config = res_config; logs.extend(res_logs); } - Err(err) => logs.push(("exception".into(), err.to_string())), + Err(err) => logs.push(("exception".into(), err.to_string().into())), } result_map.insert(script_item.uid, logs); @@ -361,7 +362,7 @@ pub async fn enhance() -> (Mapping, Vec, HashMap) { .for_each(|item| { log::debug!(target: "app", "run builtin script {}", item.uid); if let ChainType::Script(script) = item.data { - match use_script(script, config.to_owned(), "".to_string()) { + match use_script(script, config.to_owned(), "".into()) { Ok((res_config, _)) => { config = res_config; } diff --git a/src-tauri/src/enhance/script.rs b/src-tauri/src/enhance/script.rs index 42a968aaf..44a39d14a 100644 --- a/src-tauri/src/enhance/script.rs +++ b/src-tauri/src/enhance/script.rs @@ -1,6 +1,7 @@ use super::use_lowercase; use anyhow::{Error, Result}; use serde_yaml_ng::Mapping; +use smartstring::alias::String; pub fn use_script( script: String, @@ -44,7 +45,7 @@ pub fn use_script( ) })?; let mut out = copy_outputs.borrow_mut(); - out.push((level, data)); + out.push((level.into(), data.into())); Ok(JsValue::undefined()) }, ), @@ -94,7 +95,7 @@ pub fn use_script( match res { Ok(config) => Ok((use_lowercase(config), out.to_vec())), Err(err) => { - out.push(("exception".into(), err.to_string())); + out.push(("exception".into(), err.to_string().into())); Ok((config, out.to_vec())) } } @@ -121,7 +122,7 @@ fn strip_outer_quotes(s: &str) -> &str { // 转义单引号和反斜杠,用于单引号包裹的JavaScript字符串 fn escape_js_string_for_single_quote(s: &str) -> String { - s.replace('\\', "\\\\").replace('\'', "\\'") + s.replace('\\', "\\\\").replace('\'', "\\'").into() } #[test] @@ -150,7 +151,7 @@ fn test_script() { "; 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()) + let (config, results) = use_script(script.into(), config, "".into()) .expect("Script execution should succeed in test"); let _ = serde_yaml_ng::to_string(&config).expect("Failed to serialize config to YAML"); diff --git a/src-tauri/src/feat/backup.rs b/src-tauri/src/feat/backup.rs index 4a45ced08..e2f0957a2 100644 --- a/src-tauri/src/feat/backup.rs +++ b/src-tauri/src/feat/backup.rs @@ -11,6 +11,7 @@ use anyhow::{Result, anyhow}; use chrono::Utc; use reqwest_dav::list_cmd::ListFile; use serde::Serialize; +use smartstring::alias::String; use std::{fs, path::PathBuf}; #[derive(Debug, Serialize)] @@ -82,7 +83,7 @@ pub async fn restore_webdav_backup(filename: String) -> Result<()> { let backup_storage_path = app_home_dir() .map_err(|e| anyhow::anyhow!("Failed to get app home dir: {e}"))? - .join(&filename); + .join(filename.as_str()); backup::WebDavClient::global() .download(filename, backup_storage_path.clone()) .await @@ -128,7 +129,7 @@ pub async fn create_local_backup() -> Result<()> { })?; let backup_dir = local_backup_dir()?; - let target_path = backup_dir.join(&file_name); + let target_path = backup_dir.join(file_name.as_str()); if let Err(err) = move_file(temp_file_path.clone(), target_path.clone()) { logging!( @@ -196,9 +197,9 @@ pub fn list_local_backup() -> Result> { .map(|time| chrono::DateTime::::from(time).to_rfc3339()) .unwrap_or_default(); backups.push(LocalBackupFile { - filename: file_name.to_string(), - path: path.to_string_lossy().to_string(), - last_modified, + filename: file_name.into(), + path: path.to_string_lossy().into(), + last_modified: last_modified.into(), content_length: metadata.len(), }); } @@ -210,7 +211,7 @@ pub fn list_local_backup() -> Result> { /// Delete local backup pub async fn delete_local_backup(filename: String) -> Result<()> { let backup_dir = local_backup_dir()?; - let target_path = backup_dir.join(&filename); + let target_path = backup_dir.join(filename.as_str()); if !target_path.exists() { logging!( warn, @@ -227,7 +228,7 @@ pub async fn delete_local_backup(filename: String) -> Result<()> { /// Restore local backup pub async fn restore_local_backup(filename: String) -> Result<()> { let backup_dir = local_backup_dir()?; - let target_path = backup_dir.join(&filename); + let target_path = backup_dir.join(filename.as_str()); if !target_path.exists() { return Err(anyhow!("Backup file not found: {}", filename)); } @@ -259,12 +260,12 @@ pub async fn restore_local_backup(filename: String) -> Result<()> { /// Export local backup file to user selected destination pub fn export_local_backup(filename: String, destination: String) -> Result<()> { let backup_dir = local_backup_dir()?; - let source_path = backup_dir.join(&filename); + let source_path = backup_dir.join(filename.as_str()); if !source_path.exists() { return Err(anyhow!("Backup file not found: {}", filename)); } - let dest_path = PathBuf::from(destination); + let dest_path = PathBuf::from(destination.as_str()); if let Some(parent) = dest_path.parent() { fs::create_dir_all(parent)?; } diff --git a/src-tauri/src/feat/clash.rs b/src-tauri/src/feat/clash.rs index 4bb474fd5..b4143a268 100644 --- a/src-tauri/src/feat/clash.rs +++ b/src-tauri/src/feat/clash.rs @@ -6,6 +6,7 @@ use crate::{ utils::{self, logging::Type, resolve}, }; use serde_yaml_ng::{Mapping, Value}; +use smartstring::alias::String; /// Restart the Clash core pub async fn restart_clash_core() { @@ -58,7 +59,7 @@ fn after_change_clash_mode() { /// Change Clash mode (rule/global/direct/script) pub async fn change_clash_mode(mode: String) { let mut mapping = Mapping::new(); - mapping.insert(Value::from("mode"), mode.clone().into()); + mapping.insert(Value::from("mode"), Value::from(mode.as_str())); // Convert YAML mapping to JSON Value let json_value = serde_json::json!({ "mode": mode @@ -112,7 +113,7 @@ pub async fn test_delay(url: String) -> anyhow::Result { ProxyType::None }; - let user_agent = Some("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0".to_string()); + let user_agent = Some("Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0".into()); let start = Instant::now(); diff --git a/src-tauri/src/feat/profile.rs b/src-tauri/src/feat/profile.rs index 625bdfb21..47e8d4024 100644 --- a/src-tauri/src/feat/profile.rs +++ b/src-tauri/src/feat/profile.rs @@ -6,6 +6,7 @@ use crate::{ utils::logging::Type, }; use anyhow::{Result, bail}; +use smartstring::alias::String; /// Toggle proxy profile pub async fn toggle_proxy_profile(profile_index: String) { diff --git a/src-tauri/src/feat/proxy.rs b/src-tauri/src/feat/proxy.rs index a7d83b9ed..ef0630269 100644 --- a/src-tauri/src/feat/proxy.rs +++ b/src-tauri/src/feat/proxy.rs @@ -66,7 +66,7 @@ pub async fn toggle_tun_mode(not_save_file: Option) { pub async fn copy_clash_env() { // 从环境变量获取IP地址,如果没有则从配置中获取 proxy_host,默认为 127.0.0.1 let clash_verge_rev_ip = match env::var("CLASH_VERGE_REV_IP") { - Ok(ip) => ip, + Ok(ip) => ip.into(), Err(_) => Config::verge() .await .latest_ref() diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index c6bbf9d85..93d01b0a3 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -86,7 +86,7 @@ mod app_init { let url = event.urls().first().map(|u| u.to_string()); if let Some(url) = url { AsyncHandler::spawn(|| async { - if let Err(e) = resolve::resolve_scheme(url).await { + if let Err(e) = resolve::resolve_scheme(url.into()).await { logging!(error, Type::Setup, "Failed to resolve scheme: {}", e); } }); diff --git a/src-tauri/src/module/lightweight.rs b/src-tauri/src/module/lightweight.rs index 87ec61e6d..08ea8575a 100644 --- a/src-tauri/src/module/lightweight.rs +++ b/src-tauri/src/module/lightweight.rs @@ -305,7 +305,7 @@ async fn setup_light_weight_timer() -> Result<()> { interval_minutes: once_by_minutes, last_run: chrono::Local::now().timestamp(), }; - timer_map.insert(LIGHT_WEIGHT_TASK_UID.to_string(), timer_task); + timer_map.insert(LIGHT_WEIGHT_TASK_UID.into(), timer_task); } logging!( diff --git a/src-tauri/src/utils/init.rs b/src-tauri/src/utils/init.rs index 0dda26a8d..d3e3a277e 100644 --- a/src-tauri/src/utils/init.rs +++ b/src-tauri/src/utils/init.rs @@ -541,7 +541,7 @@ pub async fn startup_script() -> Result<()> { )); }; - let script_dir = PathBuf::from(&script_path); + let script_dir = PathBuf::from(script_path.as_str()); if !script_dir.exists() { return Err(anyhow::anyhow!("script not found: {}", script_path)); } @@ -553,7 +553,7 @@ pub async fn startup_script() -> Result<()> { .shell() .command(shell_type) .current_dir(working_dir) - .args(&[script_path]) + .args([script_path.as_str()]) .output() .await?; diff --git a/src-tauri/src/utils/logging.rs b/src-tauri/src/utils/logging.rs index ec08e4e26..f4c6d7407 100644 --- a/src-tauri/src/utils/logging.rs +++ b/src-tauri/src/utils/logging.rs @@ -98,21 +98,10 @@ macro_rules! wrap_err { // Case 1: Future> ($stat:expr, async) => {{ match $stat.await { - Ok(a) => Ok(a), + Ok(a) => Ok::<_, ::anyhow::Error>(a), Err(err) => { log::error!(target: "app", "{}", err); - Err(err.to_string()) - } - } - }}; - - // Case 2: Result - ($stat:expr) => {{ - match $stat { - Ok(a) => Ok(a), - Err(err) => { - log::error!(target: "app", "{}", err); - Err(err.to_string()) + Err(::anyhow::Error::msg(err.to_string())) } } }}; diff --git a/src-tauri/src/utils/network.rs b/src-tauri/src/utils/network.rs index 55fa65ce8..cc765e659 100644 --- a/src-tauri/src/utils/network.rs +++ b/src-tauri/src/utils/network.rs @@ -1,3 +1,4 @@ +use crate::config::Config; use anyhow::Result; use base64::{Engine as _, engine::general_purpose}; use isahc::prelude::*; @@ -9,14 +10,13 @@ use isahc::{ header::{HeaderMap, HeaderValue, USER_AGENT}, }, }; +use smartstring::alias::String; use std::time::{Duration, Instant}; use sysproxy::Sysproxy; use tauri::Url; use tokio::sync::Mutex; use tokio::time::timeout; -use crate::config::Config; - #[derive(Debug)] pub struct HttpResponse { status: StatusCode, @@ -80,7 +80,7 @@ impl NetworkManager { async fn record_connection_error(&self, error: &str) { let mut last_error = self.last_connection_error.lock().await; - *last_error = Some((Instant::now(), error.to_string())); + *last_error = Some((Instant::now(), error.into())); let mut count = self.connection_error_count.lock().await; *count += 1; @@ -181,8 +181,9 @@ impl NetworkManager { headers.insert( USER_AGENT, HeaderValue::from_str( - &user_agent - .unwrap_or_else(|| format!("clash-verge/v{}", env!("CARGO_PKG_VERSION"))), + &user_agent.unwrap_or_else(|| { + format!("clash-verge/v{}", env!("CARGO_PKG_VERSION")).into() + }), )?, ); @@ -240,7 +241,7 @@ impl NetworkManager { let status = response.status(); let headers = response.headers().clone(); let body = response.text().await?; - Ok::<_, anyhow::Error>(HttpResponse::new(status, headers, body)) + Ok::<_, anyhow::Error>(HttpResponse::new(status, headers, body.into())) }) .await { diff --git a/src-tauri/src/utils/resolve/mod.rs b/src-tauri/src/utils/resolve/mod.rs index 757ba79f5..93b7bcea6 100644 --- a/src-tauri/src/utils/resolve/mod.rs +++ b/src-tauri/src/utils/resolve/mod.rs @@ -1,4 +1,5 @@ use anyhow::Result; +use smartstring::alias::String; use crate::{ config::Config, diff --git a/src-tauri/src/utils/resolve/scheme.rs b/src-tauri/src/utils/resolve/scheme.rs index c34c9503f..4c7ace907 100644 --- a/src-tauri/src/utils/resolve/scheme.rs +++ b/src-tauri/src/utils/resolve/scheme.rs @@ -1,8 +1,9 @@ use anyhow::{Result, bail}; use percent_encoding::percent_decode_str; +use smartstring::alias::String; use tauri::Url; -use crate::{config::PrfItem, core::handle, logging, utils::logging::Type, wrap_err}; +use crate::{config::PrfItem, core::handle, logging, logging_error, utils::logging::Type}; pub(super) async fn resolve_scheme(param: String) -> Result<()> { log::info!(target:"app", "received deep link: {param}"); @@ -27,7 +28,7 @@ pub(super) async fn resolve_scheme(param: String) -> Result<()> { let name = link_parsed .query_pairs() .find(|(key, _)| key == "name") - .map(|(_, value)| value.into_owned()); + .map(|(_, value)| value.into()); let url_param = if let Some(query) = link_parsed.query() { let prefix = "url="; @@ -58,7 +59,11 @@ pub(super) async fn resolve_scheme(param: String) -> Result<()> { } }; let result = crate::config::profiles::profiles_append_item_safe(item).await; - let _ = wrap_err!(result); + logging_error!( + Type::Config, + "failed to import subscription url: {:?}", + result + ); handle::Handle::notice_message("import_sub_url::ok", uid); } Err(e) => { diff --git a/src-tauri/src/utils/resolve/window.rs b/src-tauri/src/utils/resolve/window.rs index 4603fee72..463812483 100644 --- a/src-tauri/src/utils/resolve/window.rs +++ b/src-tauri/src/utils/resolve/window.rs @@ -26,11 +26,11 @@ pub async fn build_new_window() -> Result { .latest_ref() .start_page .clone() - .unwrap_or("/".to_string()); + .unwrap_or("/".into()); match tauri::WebviewWindowBuilder::new( app_handle, "main", /* the unique window label */ - tauri::WebviewUrl::App(start_page.into()), + tauri::WebviewUrl::App(start_page.as_str().into()), ) .title("Clash Verge") .center() diff --git a/src-tauri/src/utils/server.rs b/src-tauri/src/utils/server.rs index db5f1b85e..48e5158c6 100644 --- a/src-tauri/src/utils/server.rs +++ b/src-tauri/src/utils/server.rs @@ -1,5 +1,3 @@ -use std::time::Duration; - use super::resolve; use crate::{ config::{Config, DEFAULT_PAC, IVerge}, @@ -13,6 +11,8 @@ use once_cell::sync::OnceCell; use parking_lot::Mutex; use port_scanner::local_port_available; use reqwest::ClientBuilder; +use smartstring::alias::String; +use std::time::Duration; use tokio::sync::oneshot; use warp::Filter; @@ -31,7 +31,7 @@ pub async fn check_singleton() -> Result<()> { let client = ClientBuilder::new() .timeout(Duration::from_millis(500)) .build()?; - let argvs: Vec = std::env::args().collect(); + let argvs: Vec = std::env::args().collect(); if argvs.len() > 1 { #[cfg(not(target_os = "macos"))] { @@ -75,8 +75,8 @@ pub fn embed_server() { } else { logging!(error, Type::Window, "轻量模式退出失败,无法恢复应用窗口"); }; - Ok::<_, warp::Rejection>(warp::reply::with_status::( - "ok".into(), + Ok::<_, warp::Rejection>(warp::reply::with_status::( + "ok".to_string(), warp::http::StatusCode::OK, )) }); @@ -111,7 +111,10 @@ pub fn embed_server() { tokio::task::spawn_local(async move { logging_error!(Type::Setup, resolve::resolve_scheme(param).await); }); - warp::reply::with_status::("ok".into(), warp::http::StatusCode::OK) + warp::reply::with_status::( + "ok".to_string(), + warp::http::StatusCode::OK, + ) }); let commands = visible.or(scheme).or(pac);