perf: add PartialEq derive to PrfSelected and PrfExtra structs for improved comparison

This commit is contained in:
Tunglies 2026-01-16 11:29:57 +08:00
parent a5bfe5f377
commit 6ee27bfe50
No known key found for this signature in database
GPG Key ID: B9B01B389469B3E8
3 changed files with 51 additions and 59 deletions

View File

@ -60,13 +60,13 @@ pub struct PrfItem {
pub file_data: Option<String>, pub file_data: Option<String>,
} }
#[derive(Default, Debug, Clone, Deserialize, Serialize)] #[derive(Default, Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct PrfSelected { pub struct PrfSelected {
pub name: Option<String>, pub name: Option<String>,
pub now: Option<String>, pub now: Option<String>,
} }
#[derive(Default, Debug, Clone, Copy, Deserialize, Serialize)] #[derive(Default, Debug, Clone, Copy, PartialEq, Deserialize, Serialize)]
pub struct PrfExtra { pub struct PrfExtra {
pub upload: u64, pub upload: u64,
pub download: u64, pub download: u64,

View File

@ -37,8 +37,10 @@ pub struct CleanupResult {
macro_rules! patch { macro_rules! patch {
($lv: expr, $rv: expr, $key: tt) => { ($lv: expr, $rv: expr, $key: tt) => {
if ($rv.$key).is_some() { if let Some(ref val) = $rv.$key {
$lv.$key = $rv.$key.to_owned(); if Some(val) != $lv.$key.as_ref() {
$lv.$key = Some(val.to_owned());
}
} }
}; };
} }
@ -53,21 +55,22 @@ impl IProfiles {
} }
}; };
match help::read_yaml::<Self>(&path).await { let mut profiles = match help::read_yaml::<Self>(&path).await {
Ok(mut profiles) => { Ok(profiles) => profiles,
let items = profiles.items.get_or_insert_with(Vec::new);
for item in items.iter_mut() {
if item.uid.is_none() {
item.uid = Some(help::get_uid("d").into());
}
}
profiles
}
Err(err) => { Err(err) => {
logging!(error, Type::Config, "{err}"); logging!(error, Type::Config, "{err}");
Self::default() return Self::default();
}
};
let items = profiles.items.get_or_insert_with(Vec::new);
for item in items.iter_mut() {
if item.uid.is_none() {
item.uid = Some(help::get_uid("d").into());
} }
} }
profiles
} }
pub async fn save_file(&self) -> Result<()> { pub async fn save_file(&self) -> Result<()> {
@ -103,38 +106,28 @@ impl IProfiles {
pub fn get_item(&self, uid: impl AsRef<str>) -> Result<&PrfItem> { pub fn get_item(&self, uid: impl AsRef<str>) -> Result<&PrfItem> {
let uid_str = uid.as_ref(); let uid_str = uid.as_ref();
if let Some(items) = self.items.as_ref() { self.items
for each in items.iter() { .as_ref()
if let Some(uid_val) = &each.uid .ok_or_else(|| anyhow::anyhow!("no profile items found"))?
&& uid_val.as_str() == uid_str .iter()
{ .find(|each| each.uid.as_ref().is_some_and(|uid_val| uid_val.as_str() == uid_str))
return Ok(each); .ok_or_else(|| anyhow::anyhow!("failed to get the profile item \"uid:{}\"", uid_str))
}
}
}
bail!("failed to get the profile item \"uid:{}\"", uid_str);
} }
/// append new item /// append new item
/// if the file_data is some /// if the file_data is some
/// then should save the data to file /// then should save the data to file
pub async fn append_item(&mut self, item: &mut PrfItem) -> Result<()> { pub async fn append_item(&mut self, item: &mut PrfItem) -> Result<()> {
let uid = &item.uid; anyhow::ensure!(item.uid.is_some(), "the uid should not be null");
if uid.is_none() {
bail!("the uid should not be null");
}
// save the file data // save the file data
// move the field value after save // move the field value after save
if let Some(file_data) = item.file_data.take() { if let Some(file_data) = item.file_data.take() {
if item.file.is_none() { anyhow::ensure!(item.file.is_some(), "the file should not be null");
bail!("the file should not be null");
}
let file = item let file = item
.file .file
.clone() .as_ref()
.ok_or_else(|| anyhow::anyhow!("file field is required when file_data is provided"))?; .ok_or_else(|| anyhow::anyhow!("file field is required when file_data is provided"))?;
let path = dirs::app_profiles_dir()?.join(file.as_str()); let path = dirs::app_profiles_dir()?.join(file.as_str());
@ -143,17 +136,14 @@ impl IProfiles {
.with_context(|| format!("failed to write to file \"{file}\""))?; .with_context(|| format!("failed to write to file \"{file}\""))?;
} }
if self.current.is_none() && (item.itype == Some("remote".into()) || item.itype == Some("local".into())) { if self.current.is_none()
self.current = uid.to_owned(); && let Some(t) = item.itype.as_deref()
&& (t == "remote" || t == "local")
{
self.current = item.uid.to_owned();
} }
if self.items.is_none() { self.items.get_or_insert_default().push(std::mem::take(item));
self.items = Some(vec![]);
}
if let Some(items) = self.items.as_mut() {
items.push(item.to_owned());
}
Ok(()) Ok(())
} }
@ -200,26 +190,27 @@ impl IProfiles {
/// update the item value /// update the item value
pub async fn patch_item(&mut self, uid: &String, item: &PrfItem) -> Result<()> { pub async fn patch_item(&mut self, uid: &String, item: &PrfItem) -> Result<()> {
let mut items = self.items.take().unwrap_or_default(); let items = self
.items
.as_mut()
.ok_or_else(|| anyhow::anyhow!("no profile items found"))?;
for each in items.iter_mut() { let target = items.iter_mut().find(|each| each.uid.as_ref() == Some(uid));
if each.uid.as_ref() == Some(uid) {
patch!(each, item, itype);
patch!(each, item, name);
patch!(each, item, desc);
patch!(each, item, file);
patch!(each, item, url);
patch!(each, item, selected);
patch!(each, item, extra);
patch!(each, item, updated);
patch!(each, item, option);
self.items = Some(items); if let Some(each) = target {
return self.save_file().await; patch!(each, item, itype);
} patch!(each, item, name);
patch!(each, item, desc);
patch!(each, item, file);
patch!(each, item, url);
patch!(each, item, selected);
patch!(each, item, extra);
patch!(each, item, updated);
patch!(each, item, option);
return self.save_file().await;
} }
self.items = Some(items);
bail!("failed to find the profile item \"uid:{uid}\"") bail!("failed to find the profile item \"uid:{uid}\"")
} }

View File

@ -25,6 +25,7 @@ pub struct TimerTask {
pub last_run: i64, // Timestamp of last execution pub last_run: i64, // Timestamp of last execution
} }
// TODO 一个 Timer 负责轻量, 一个 Timer 负责订阅更新。当前会生产 N(订阅数量) + 1 个定时任务
pub struct Timer { pub struct Timer {
/// cron manager /// cron manager
pub delay_timer: Arc<RwLock<DelayTimer>>, pub delay_timer: Arc<RwLock<DelayTimer>>,