Skip to content

Commit

Permalink
Manual implementation of clippy suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
leontoeides committed Feb 9, 2024
1 parent 613939f commit 50f5c69
Show file tree
Hide file tree
Showing 22 changed files with 353 additions and 447 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@

#![forbid(unsafe_code)]
#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)]
#![allow(clippy::module_name_repetitions)]
#![doc(html_favicon_url = "https://www.arkiteq.ca/crates/indicium/icon.png")]
#![doc(html_logo_url = "https://www.arkiteq.ca/crates/indicium/logo.png")]

Expand Down
10 changes: 3 additions & 7 deletions src/simple/autocomplete/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,15 +100,15 @@ impl<K: Hash + Ord> SearchIndex<K> {
) -> Vec<String> {
// Split search `String` into keywords according to the `SearchIndex`
// settings. Force "use entire string as a keyword" option off:
let mut keywords: Vec<KString> = self.string_keywords(string, SplitContext::Searching);
let mut keywords: Vec<KString> = self.string_keywords(string, &SplitContext::Searching);

// For debug builds:
#[cfg(debug_assertions)]
tracing::debug!("autocompleting: {:?}", keywords);

// Pop the last keyword off the list - the keyword that we'll be
// autocompleting:
if let Some(last_keyword) = keywords.pop() {
keywords.pop().map_or_else(Vec::new, |last_keyword| {
// Perform `And` search for entire string without the last keyword:
let search_results: BTreeSet<&K> = self.internal_search_and(keywords.as_slice());

Expand Down Expand Up @@ -218,10 +218,6 @@ impl<K: Hash + Ord> SearchIndex<K> {
})
// Collect all string autocompletions into a `Vec`:
.collect()
} else {
// The search string did not have a last keyword to autocomplete.
// Return an empty `Vec`:
Vec::new()
} // if
}) // map_or_else
} // fn
} // impl
10 changes: 3 additions & 7 deletions src/simple/autocomplete/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,15 @@ impl<K: Hash + Ord> SearchIndex<K> {
) -> Vec<String> {
// Split search `String` into keywords according to the `SearchIndex`
// settings. Force "use entire string as a keyword" option off:
let mut keywords: Vec<KString> = self.string_keywords(string, SplitContext::Searching);
let mut keywords: Vec<KString> = self.string_keywords(string, &SplitContext::Searching);

// For debug builds:
#[cfg(debug_assertions)]
tracing::debug!("autocompleting: {:?}", keywords);

// Pop the last keyword off the list. It's the keyword that we'll be
// autocompleting:
if let Some(last_keyword) = keywords.pop() {
keywords.pop().map_or_else(Vec::new, |last_keyword| {
// Autocomplete the last keyword:
let mut autocompletions: Vec<&KString> = self
.b_tree_map
Expand Down Expand Up @@ -216,10 +216,6 @@ impl<K: Hash + Ord> SearchIndex<K> {
})
// Collect all string autocompletions into a `Vec`:
.collect()
} else {
// The search string did not have a last keyword to autocomplete.
// Return an empty `Vec`:
Vec::new()
} // if
}) // map_or_else
} // fn
} // impl
1 change: 1 addition & 0 deletions src/simple/default.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::cmp::Ord;
/// `SearchIndex::new()` or `SearchIndexBuilder`.

impl<K: Ord> Default for SearchIndex<K> {
#![allow(clippy::too_many_lines)]
fn default() -> Self {
Self::new(
SearchType::Live, // Search type.
Expand Down
55 changes: 24 additions & 31 deletions src/simple/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,40 +159,33 @@ impl<K: Clone + Ord> SearchIndex<K> {
.for_each(|keyword|
// Attempt to get mutuable reference to the _keyword entry_ in
// the search index:
match self.b_tree_map.get_mut(&keyword) {
// If keyword was found in search index, add _key reference_
// for this record to _keyword entry_:
Some(keys) => {
// Check if the maximum number of keys per keyword
// (records per keyword) limit has been reached. Note
// that the `dump_keyword` does not observe this
// limit.
if keys.len() < self.maximum_keys_per_keyword
|| self.dump_keyword == Some(keyword.as_ref().into()) {
if let Some(keys) = self.b_tree_map.get_mut(&keyword) {
// Check if the maximum number of keys per keyword
// (records per keyword) limit has been reached. Note
// that the `dump_keyword` does not observe this
// limit.
if keys.len() < self.maximum_keys_per_keyword
|| self.dump_keyword == Some(keyword.as_ref().into()) {
// If it hasn't, insert the key (record) into the
// list:
keys.insert(key.clone());
} else {
// If the limit has been reached, do not insert.
// Display warning for debug builds.
#[cfg(debug_assertions)]
tracing::warn!(
"Internal table limit of {} keys per keyword has been reached on insert. \
Record was not attached to `{}` keyword. \
This will impact accuracy of results. \
For this data set, consider using a more comprehensive search solution like MeiliSearch.",
self.maximum_keys_per_keyword,
keyword,
); // warn!
} // if
}, // Some
// If keyword was not found in search index, initialize
// _keyword entry_ with the _key reference_ for this record:
None => {
let mut b_tree_set = BTreeSet::new();
b_tree_set.insert(key.clone());
self.b_tree_map.insert(keyword.as_ref().into(), b_tree_set);
}, // None
} else {
// If the limit has been reached, do not insert.
// Display warning for debug builds.
#[cfg(debug_assertions)]
tracing::warn!(
"Internal table limit of {} keys per keyword has been reached on insert. \
Record was not attached to `{}` keyword. \
This will impact accuracy of results. \
For this data set, consider using a more comprehensive search solution like MeiliSearch.",
self.maximum_keys_per_keyword,
keyword,
); // warn!
} // if
} else {
let mut b_tree_set = BTreeSet::new();
b_tree_set.insert(key.clone());
self.b_tree_map.insert(keyword.as_ref().into(), b_tree_set);
} // match
); // for_each
} // fn
Expand Down
9 changes: 5 additions & 4 deletions src/simple/internal/eddie/eddie_autocomplete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,11 @@ impl<K: Hash + Ord> SearchIndex<K> {
pub fn eddie_autocomplete(&self, keyword: &str) -> Vec<&str> {
// If case sensitivity set, leave case intact. Otherwise, normalize
// keyword to lower case:
let keyword = match self.case_sensitive {
true => keyword.to_string(),
false => keyword.to_lowercase(),
}; // match
let keyword = if self.case_sensitive {
keyword.to_string()
} else {
keyword.to_lowercase()
}; // if

// Call global autocompletion provider:
self.eddie_global_autocomplete(&keyword)
Expand Down
13 changes: 4 additions & 9 deletions src/simple/internal/eddie/eddie_context_autocomplete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ impl<K: Hash + Ord> SearchIndex<K> {
// Attempt to find the top matches for the user's (partial) keyword
// using the selected string similarity metric defined in the
// `SearchIndex`:
if let Some(eddie_metric) = &self.eddie_metric {
match eddie_metric {
self.eddie_metric
.as_ref()
.map_or_else(Vec::new, |eddie_metric| match eddie_metric {
EddieMetric::DamerauLevenshtein => self
.eddie_autocomplete_context_damerau_levenshtein(
index_range,
Expand All @@ -84,12 +85,6 @@ impl<K: Hash + Ord> SearchIndex<K> {
EddieMetric::Levenshtein => self
.eddie_autocomplete_context_levenshtein(index_range, key_set, user_keyword)
.collect(),
} // match
} else {
// No string similarity metric was defined in the `SearchIndex`
// settings. Fuzzy string matching effectively turned off.
// Return an empty `Vec` to the caller:
vec![]
} // if
}) // map_or_else
} // fn
} // impl
6 changes: 3 additions & 3 deletions src/simple/internal/eddie/eddie_global_autocomplete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,11 @@ impl<K: Hash + Ord> SearchIndex<K> {
// Attempt to find the top matches for the user's (partial) keyword
// using the selected string similarity metric defined in the
// `SearchIndex`:
self.eddie_metric.as_ref().map_or_else(
self.eddie_metric.as_ref().map_or_else(
// No string similarity metric was defined in the `SearchIndex`
// settings. Fuzzy string matching effectively turned off.
// Return an empty `Vec` to the caller:
|| vec![],
std::vec::Vec::new,
|eddie_metric| match eddie_metric {
EddieMetric::DamerauLevenshtein => self
.eddie_autocomplete_global_damerau_levenshtein(index_range, user_keyword)
Expand All @@ -83,7 +83,7 @@ impl<K: Hash + Ord> SearchIndex<K> {
EddieMetric::Levenshtein => self
.eddie_autocomplete_global_levenshtein(index_range, user_keyword)
.collect(),
} // match
}, // match
) // map_or_else
} // fn
} // impl
13 changes: 4 additions & 9 deletions src/simple/internal/eddie/eddie_global_keyword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ impl<K: Hash + Ord> SearchIndex<K> {

// Attempt to find the closest match for the user's keyword using the
// selected string similarity metric defined in the `SearchIndex`:
if let Some(eddie_metric) = &self.eddie_metric {
match eddie_metric {
self.eddie_metric
.as_ref()
.and_then(|eddie_metric| match eddie_metric {
EddieMetric::DamerauLevenshtein => {
self.eddie_keyword_global_damerau_levenshtein(index_range, user_keyword)
}
Expand All @@ -72,12 +73,6 @@ impl<K: Hash + Ord> SearchIndex<K> {
EddieMetric::Levenshtein => {
self.eddie_keyword_global_levenshtein(index_range, user_keyword)
}
} // match
} else {
// No string similarity metric was defined in the `SearchIndex`
// settings. Fuzzy string matching effectively turned off.
// Return a `None` to the caller:
None
} // if
}) // map_or
} // fn
} // impl
9 changes: 5 additions & 4 deletions src/simple/internal/eddie/eddie_keyword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,11 @@ impl<K: Hash + Ord> SearchIndex<K> {
pub fn eddie_keyword(&self, keyword: &str) -> Option<&str> {
// If case sensitivity set, leave case intact. Otherwise, normalize
// keyword to lower case:
let keyword = match self.case_sensitive {
true => keyword.to_string(),
false => keyword.to_lowercase(),
}; // match
let keyword = if self.case_sensitive {
keyword.to_string()
} else {
keyword.to_lowercase()
}; // if

// Call global keyword subtitution provider:
self.eddie_global_keyword(&keyword)
Expand Down
4 changes: 2 additions & 2 deletions src/simple/internal/fuzzy_top_scores/with_capacity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ use std::{cmp::Ord, cmp::PartialOrd, hash::Hash};

impl<'a, K: Hash + Ord, S: PartialOrd> FuzzyTopScores<'a, K, S> {
// -------------------------------------------------------------------------
//
#![allow(clippy::default_trait_access)]
/// Instantiates a new "top scores" struct with the caller provided
/// capacity. If the caller wants to track the "top 10 matches" for a user
/// provided keyword, the caller would call `FuzzyTopScores::with_capacity(10)`.

pub(crate) fn with_capacity(capacity: usize) -> FuzzyTopScores<'a, K, S> {
FuzzyTopScores {
top: HashMap::with_capacity_and_hasher(capacity, std::default::Default::default()), // HashMap
top: HashMap::with_capacity_and_hasher(capacity, std::default::Default::default()),
bottom: None,
capacity,
} // FuzzyTopScores
Expand Down
2 changes: 1 addition & 1 deletion src/simple/internal/indexable_keywords.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ impl<K: Ord> SearchIndex<K> {
// settings. Note that `string_keywords` will allow "use entire
// string as a keyword" if enabled in user settings. Flatten the
// string's keywords into the `HashSet`:
.flat_map(|string| self.string_keywords(&string, SplitContext::Indexing))
.flat_map(|string| self.string_keywords(&string, &SplitContext::Indexing))
// Collect all keywords into a `HashSet`:
.collect()
} // fn
Expand Down
28 changes: 13 additions & 15 deletions src/simple/internal/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,19 @@ impl<K: Hash + Ord> SearchIndex<K> {
}; // if */

// Attempt to get matching keys for the search keyword from BTreeMap:
let search_results: BTreeSet<&K> = if let Some(keys) = self.b_tree_map.get(keyword) {
// Attempt to get matching keys for search keyword:
keys
// Iterate over all matching keys and only return
// `maximum_search_results` number of keys:
.iter()
// Only return `maximum_search_results` number of keys:
.take(self.maximum_keys_per_keyword)
// Insert a reference to each resulting key into the hash set:
.collect()
} else {
// The search keyword did not result in any matches. Return an
// empty `BTreeSet`:
BTreeSet::new()
}; // if
let search_results: BTreeSet<&K> =
self.b_tree_map
.get(keyword)
.map_or_else(BTreeSet::new, |keys| {
keys
// Iterate over all matching keys and only return
// `maximum_search_results` number of keys:
.iter()
// Only return `maximum_search_results` number of keys:
.take(self.maximum_keys_per_keyword)
// Insert a reference to each resulting key into hash set:
.collect()
}); // map_or_else

// For debug builds:
#[cfg(debug_assertions)]
Expand Down
53 changes: 22 additions & 31 deletions src/simple/internal/search_and.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,31 +32,27 @@ impl<K: Hash + Ord> SearchIndex<K> {
Some(keyword_results) => {
search_results = Some(
// Check if `search_results` is already populated:
match &search_results {
// If `search_results` is is not empty, intersect
// the current keyword's results with the master
// search results:
Some(search_results) => search_results
// Iterate over each search result record:
.iter()
// Intersect the search result record with the
// keyword results. If the search result record
// doesn't exist in this keyword's results,
// filter it out:
.filter(|key| keyword_results.contains(key))
// Copy each key from the `Intersection`
// iterator or we'll get a doubly-referenced
// `&&K` key:
.copied()
// And collect each key into a `BTreeSet` that
// will become the new `search_results`:
.collect(),

// If `search_results` is empty, initialize it with
// the first keyword's full search results:
None => self.internal_keyword_search(keyword),
}, // match
);
search_results.as_ref().map_or_else(
|| self.internal_keyword_search(keyword),
|search_results| {
search_results
// Iterate over each search result record:
.iter()
// Intersect the search result record with the
// keyword results. If the search result record
// doesn't exist in this keyword's results,
// filter it out:
.filter(|key| keyword_results.contains(key))
// Copy each key from the `Intersection`
// iterator or we'll get a doubly-referenced
// `&&K` key:
.copied()
// And collect each key into a `BTreeSet` that
// will become the new `search_results`:
.collect()
},
), // map_or_else
); // Some
} // Some

// Any keyword that returns no results will short-circuit
Expand All @@ -80,11 +76,6 @@ impl<K: Hash + Ord> SearchIndex<K> {
} // if

// Return search results:
match search_results {
// If master `search_results` is not empty, return it:
Some(search_results) => search_results,
// If master `search_results` is empty, return an empty `BTreeSet`:
None => BTreeSet::new(),
} // match
search_results.map_or_else(BTreeSet::new, |search_results| search_results)
} // fn
} // impl
4 changes: 2 additions & 2 deletions src/simple/internal/search_top_scores/with_capacity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ use std::{cmp::Ord, hash::Hash};

impl<'a, K: Hash + Ord> SearchTopScores<'a, K> {
// -------------------------------------------------------------------------
//
#![allow(clippy::default_trait_access)]
/// Instantiates a new "top scores" struct with the caller provided
/// capacity. If the caller wants to track the "top 10 matches" for a user
/// provided keyword, the caller would call `SearchTopScores::with_capacity(10)`.

pub(crate) fn with_capacity(capacity: usize) -> SearchTopScores<'a, K> {
SearchTopScores {
top: HashMap::with_capacity_and_hasher(capacity, std::default::Default::default()), // HashMap
top: HashMap::with_capacity_and_hasher(capacity, std::default::Default::default()),
bottom: None,
capacity,
} // SearchTopScores
Expand Down
Loading

0 comments on commit 50f5c69

Please sign in to comment.