Use std::collections::HashSet for aliases for better perfromance and guaranteed uniqueness

This commit is contained in:
Tahaa-Dev 2026-07-21 01:09:46 +03:00 committed by Taha Mahmoud
parent f8899a4a91
commit b3ae1e6a28
6 changed files with 44 additions and 22 deletions

View File

@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::fmt::{self, Display, Formatter};
use serde::{Deserialize, Serialize};
@ -12,7 +13,7 @@ pub struct DirV4<'a> {
pub rank: Rank,
pub last_accessed: Epoch,
#[serde(borrow)]
pub aliases: Vec<Cow<'a, str>>,
pub aliases: HashSet<Cow<'a, str>>,
}
#[derive(Clone, Debug, Deserialize, Serialize)]
@ -26,7 +27,7 @@ pub struct DirV3<'a> {
pub trait Dir {
fn path(&self) -> &str;
fn score(&self, now: Epoch) -> Rank;
fn aliases(&self) -> &[Cow<'_, str>];
fn aliases(&self) -> Option<&HashSet<Cow<'_, str>>>;
}
impl Dir for DirV4<'_> {
@ -48,8 +49,8 @@ impl Dir for DirV4<'_> {
}
}
fn aliases(&self) -> &[Cow<'_, str>] {
&self.aliases
fn aliases(&self) -> Option<&HashSet<Cow<'_, str>>> {
Some(&self.aliases)
}
}
@ -78,8 +79,8 @@ impl Dir for DirV3<'_> {
}
}
fn aliases(&self) -> &[Cow<'_, str>] {
return &[];
fn aliases(&self) -> Option<&HashSet<Cow<'_, str>>> {
None
}
}
@ -118,8 +119,10 @@ impl<'a, T: Dir> Display for DirDisplay<'a, T> {
write!(f, "{score:>6.1}{}", self.separator)?;
}
if self.aliases {
for alias in self.dir.aliases() {
if self.aliases
&& let Some(aliases) = self.dir.aliases()
{
for alias in aliases {
write!(f, "{} ", alias)?;
}
write!(f, "{}", self.separator)?;

View File

@ -1,6 +1,7 @@
mod dir;
mod stream;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::{fs, io};
@ -78,12 +79,15 @@ impl Database {
Some(dir) => {
dir.rank = (dir.rank + by).max(0.0);
if let Some(al) = alias {
dir.aliases.push(al.into().into());
dir.aliases.insert(al.into().into());
}
}
None => {
let aliases =
if let Some(alias) = alias { vec![alias.into().into()] } else { Vec::new() };
let aliases = if let Some(alias) = alias {
HashSet::from([alias.into().into()])
} else {
HashSet::new()
};
dirs.push(DirV4 {
path: path.into().into(),
rank: by.max(0.0),
@ -107,8 +111,11 @@ impl Database {
alias: Option<impl AsRef<str> + Into<String>>,
) {
self.with_dirs_mut(|dirs| {
let aliases =
if let Some(alias) = alias { vec![alias.into().into()] } else { Vec::new() };
let aliases = if let Some(alias) = alias {
HashSet::from([alias.into().into()])
} else {
HashSet::new()
};
dirs.push(DirV4 { path: path.into().into(), rank, last_accessed: now, aliases })
});
self.with_dirty_mut(|dirty| *dirty = true);
@ -128,12 +135,15 @@ impl Database {
dir.rank = (dir.rank + by).max(0.0);
dir.last_accessed = now;
if let Some(al) = alias {
dir.aliases.push(al.into().into());
dir.aliases.insert(al.into().into());
}
}
None => {
let aliases =
if let Some(alias) = alias { vec![alias.into().into()] } else { Vec::new() };
let aliases = if let Some(alias) = alias {
HashSet::from([alias.into().into()])
} else {
HashSet::new()
};
dirs.push(DirV4 {
path: path.into().into(),
rank: by.max(0.0),
@ -278,7 +288,7 @@ impl Database {
path: dir.path,
rank: dir.rank,
last_accessed: dir.last_accessed,
aliases: Vec::new(),
aliases: HashSet::new(),
})
.collect()
}

View File

@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::iter::Rev;
use std::ops::Range;
use std::path::Path;
@ -109,10 +110,10 @@ impl<'a> Stream<'a> {
true
}
fn match_aliases(&self, aliases: &[Cow<'a, str>]) -> bool {
fn match_aliases(&self, aliases: &HashSet<Cow<'a, str>>) -> bool {
for keyword in self.options.keywords.iter().rev() {
// Alias matching is intended to be case-sensitive
if aliases.iter().any(|a| a == keyword.as_str()) {
if aliases.contains(keyword.as_str()) {
return true;
}
}

View File

@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::io::{BufRead, BufReader};
use std::process::{Child, ChildStdout, Command, Stdio};
use std::str;
@ -64,7 +65,7 @@ impl Iter {
path: Cow::Owned(path.to_string()),
rank: 1.0,
last_accessed: timestamp as Epoch,
aliases: Vec::new(),
aliases: HashSet::new(),
};
Ok(dir)
}

View File

@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
@ -56,7 +57,7 @@ impl<R: BufRead> Iter<R> {
path: Cow::Owned(path.to_string()),
rank,
last_accessed: 0,
aliases: Vec::new(),
aliases: HashSet::new(),
})
}
}

View File

@ -1,4 +1,5 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::path::PathBuf;
@ -54,7 +55,12 @@ impl<R: BufRead> Iter<R> {
let path = split.next().ok_or_else(err)?;
Ok(DirV4 { path: Cow::Owned(path.to_string()), rank, last_accessed, aliases: Vec::new() })
Ok(DirV4 {
path: Cow::Owned(path.to_string()),
rank,
last_accessed,
aliases: HashSet::new(),
})
}
}