Use cow for keys
This commit is contained in:
parent
e0be452bdb
commit
0642b909c3
@ -168,7 +168,8 @@ fn reduce_selections(
|
|||||||
options.ignore_case,
|
options.ignore_case,
|
||||||
);
|
);
|
||||||
|
|
||||||
if key_set_operation_result.contains(&key) {
|
// TODO: Do not allocate
|
||||||
|
if key_set_operation_result.contains(&key.into_owned()) {
|
||||||
Some(swd.desc)
|
Some(swd.desc)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -268,6 +269,7 @@ fn to_ordered_counts(options: &Options, sels: Vec<Selection>) -> LinkedHashMap<S
|
|||||||
|
|
||||||
for i in sels {
|
for i in sels {
|
||||||
let key = crate::utils::get_key(
|
let key = crate::utils::get_key(
|
||||||
|
// TODO: Do not allocate
|
||||||
&i,
|
&i,
|
||||||
options.skip_whitespace,
|
options.skip_whitespace,
|
||||||
options.regex.as_ref(),
|
options.regex.as_ref(),
|
||||||
@ -279,7 +281,8 @@ fn to_ordered_counts(options: &Options, sels: Vec<Selection>) -> LinkedHashMap<S
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let entry: &mut usize = ret.entry(key).or_insert(0);
|
// TODO: Do not allocate
|
||||||
|
let entry: &mut usize = ret.entry(key.into_owned()).or_insert(0);
|
||||||
*entry = entry.saturating_add(1);
|
*entry = entry.saturating_add(1);
|
||||||
}
|
}
|
||||||
ret
|
ret
|
||||||
|
50
src/utils.rs
50
src/utils.rs
@ -1,56 +1,74 @@
|
|||||||
use kakplugin::Selection;
|
// use kakplugin::Selection;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::{Borrow, Cow},
|
||||||
collections::hash_map::DefaultHasher,
|
collections::hash_map::DefaultHasher,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn get_key(
|
/// Gets a key out of a selection
|
||||||
// TODO: Use Cow
|
///
|
||||||
selection: &Selection,
|
/// # Examples
|
||||||
skip_whitespace: bool,
|
///
|
||||||
|
/// ```
|
||||||
|
/// assert_eq!(get_key(" asdf\n", false, None, false), "asdf\n");
|
||||||
|
/// assert_eq!(get_key(" asdf\n", true, None, false), " asdf\n");
|
||||||
|
/// assert_eq!(get_key(" as1f\n", false, Some("\w+"), false), "as");
|
||||||
|
/// assert_eq!(get_key(" aS1F\n", false, Some("\w+"), true), "as1f");
|
||||||
|
/// ```
|
||||||
|
pub fn get_key<'sel>(
|
||||||
|
selection: &'sel str,
|
||||||
|
preserve_whitespace: bool,
|
||||||
regex: Option<&Regex>,
|
regex: Option<&Regex>,
|
||||||
ignore_case: bool,
|
ignore_case: bool,
|
||||||
) -> String {
|
) -> Cow<'sel, str> {
|
||||||
// Strip whitespace if requested
|
// Strip whitespace if requested
|
||||||
let mut key = if skip_whitespace {
|
let mut key = if preserve_whitespace {
|
||||||
selection.as_str()
|
// TODO: Does this need to be swapped?
|
||||||
|
selection
|
||||||
} else {
|
} else {
|
||||||
selection.trim()
|
selection.trim()
|
||||||
};
|
};
|
||||||
|
|
||||||
// If they requested a regex match, set the key to the string slice of that match
|
// If they requested a regex match, set the key to the string slice of that match
|
||||||
if let Some(regex_match) = (|| {
|
if let Some(regex_match) = (|| {
|
||||||
let captures = regex.as_ref()?.captures(key)?;
|
// let captures = regex.as_ref()?.captures(&key)?;
|
||||||
|
let captures = regex.as_ref()?.captures(key.borrow())?;
|
||||||
captures
|
captures
|
||||||
.get(1)
|
.get(1)
|
||||||
.or_else(|| captures.get(0))
|
.or_else(|| captures.get(0))
|
||||||
.map(|m| m.as_str())
|
.map(|m| m.as_str())
|
||||||
})() {
|
})() {
|
||||||
key = regex_match;
|
key = regex_match;
|
||||||
|
// Cow::Borrowed(regex_match)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore case if requested
|
// Ignore case if requested
|
||||||
// Lowercase at the end to not mangle regex
|
|
||||||
if ignore_case {
|
if ignore_case {
|
||||||
key.to_lowercase()
|
// Lowercase at the end to not mangle regex
|
||||||
|
// TODO: Do not allocate if it is already lowercased
|
||||||
|
// Need to_lowercase(&self) -> Cow<str>
|
||||||
|
if !key.as_bytes().iter().any(u8::is_ascii_uppercase) {
|
||||||
|
Cow::Borrowed(key)
|
||||||
} else {
|
} else {
|
||||||
// TODO: Do not perform an allocation here
|
Cow::Owned(key.to_ascii_lowercase())
|
||||||
key.to_string()
|
}
|
||||||
|
} else {
|
||||||
|
Cow::Borrowed(key)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a key out of a selection based on options
|
/// Get a key out of a selection based on options
|
||||||
pub fn get_hash(
|
pub fn get_hash(
|
||||||
// TODO: Accept any Into<AsRef<Selection>>
|
// TODO: Accept any Into<AsRef<Selection>>
|
||||||
selection: &Selection,
|
selection: &str,
|
||||||
skip_whitespace: bool,
|
preserve_whitespace: bool,
|
||||||
regex: Option<&Regex>,
|
regex: Option<&Regex>,
|
||||||
ignore_case: bool,
|
ignore_case: bool,
|
||||||
) -> u64 {
|
) -> u64 {
|
||||||
let mut hasher = DefaultHasher::new();
|
let mut hasher = DefaultHasher::new();
|
||||||
|
|
||||||
get_key(selection, skip_whitespace, regex, ignore_case).hash(&mut hasher);
|
get_key(&selection, preserve_whitespace, regex, ignore_case).hash(&mut hasher);
|
||||||
|
|
||||||
hasher.finish()
|
hasher.finish()
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ pub fn xlookup(options: &Options) -> Result<String, KakError> {
|
|||||||
|
|
||||||
set_selections(selections.iter().map(|key| {
|
set_selections(selections.iter().map(|key| {
|
||||||
lookup_table
|
lookup_table
|
||||||
.get(&get_hash(key, false, None, false))
|
.get(&get_hash(&key, false, None, false))
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|| {
|
|| {
|
||||||
eprintln!("Key '{key}' not found",);
|
eprintln!("Key '{key}' not found",);
|
||||||
@ -48,7 +48,7 @@ pub fn xlookup(options: &Options) -> Result<String, KakError> {
|
|||||||
fn build_lookuptable(mut selections: Vec<Selection>) -> Result<BTreeMap<u64, Selection>, KakError> {
|
fn build_lookuptable(mut selections: Vec<Selection>) -> Result<BTreeMap<u64, Selection>, KakError> {
|
||||||
let mut iter = selections.array_chunks_mut();
|
let mut iter = selections.array_chunks_mut();
|
||||||
let ret = iter.try_fold(BTreeMap::new(), |mut acc, [key, value]| {
|
let ret = iter.try_fold(BTreeMap::new(), |mut acc, [key, value]| {
|
||||||
match acc.entry(get_hash(key, false, None, false)) {
|
match acc.entry(get_hash(&key, false, None, false)) {
|
||||||
Occupied(_) => Err(KakError::Custom(format!("Duplicate key '{key}'"))),
|
Occupied(_) => Err(KakError::Custom(format!("Duplicate key '{key}'"))),
|
||||||
Vacant(v) => {
|
Vacant(v) => {
|
||||||
v.insert(value.clone());
|
v.insert(value.clone());
|
||||||
@ -76,7 +76,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
macro_rules! hsh {
|
macro_rules! hsh {
|
||||||
($expr:expr) => {
|
($expr:expr) => {
|
||||||
get_hash(&$expr.to_string(), false, None, false)
|
get_hash($expr, false, None, false)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#[test]
|
#[test]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user