perf: utilize smartstring for string handling (#5149)

* perf: utilize smartstring for string handling

- Updated various modules to replace standard String with smartstring::alias::String for improved performance and memory efficiency.
- Adjusted string manipulations and conversions throughout the codebase to ensure compatibility with the new smartstring type.
- Enhanced readability and maintainability by using `.into()` for conversions where applicable.
- Ensured that all instances of string handling in configuration, logging, and network management leverage the benefits of smartstring.

* fix: replace wrap_err with stringify_err for better error handling in UWP tool invocation

* refactor: update import path for StringifyErr and adjust string handling in sysopt

* fix: correct import path for CmdResult in UWP module

* fix: update argument type for execute_sysproxy_command to use std::string::String

* fix: add missing CmdResult import in UWP platform module

* fix: improve string handling and error messaging across multiple files

* style: format code for improved readability and consistency across multiple files

* fix: remove unused file
This commit is contained in:
Tunglies
2025-10-22 16:25:44 +08:00
committed by GitHub
parent fe96a7030a
commit a05ea64bcd
50 changed files with 361 additions and 272 deletions

View File

@@ -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(())

View File

@@ -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<String>,
option: Option<PrfOption>,
) -> Result<PrfItem> {
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<String>) -> Result<PrfItem> {
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<String>) -> Result<PrfItem> {
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<PrfItem> {
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<PrfItem> {
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<PrfItem> {
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")
}
}

View File

@@ -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}");
}
}

View File

@@ -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<Mapping>,
@@ -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());
}
});

View File

@@ -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");