use crate::simple::search_index::SearchIndex;
use kstring::KString;
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum SplitContext {
Indexing = 0,
Searching = 1,
}
#[inline]
pub fn exclude_keyword(keyword: &str, exclude_keywords: Option<&Vec<KString>>) -> bool {
exclude_keywords
.as_ref()
.is_some_and(|exclude_keywords| exclude_keywords
.iter()
.any(|excluded| excluded.as_str() == keyword)
) }
#[test]
fn test_exclude_keyword() {
let excluded_keywords: Option<Vec<KString>> = Some(vec![
"awake".into(),
"arise".into(),
"or".into(),
"be".into(),
"for".into(),
"ever".into(),
"fall’n".into(),
]);
assert!(exclude_keyword("arise", excluded_keywords.as_ref()));
assert!(!exclude_keyword("arose", excluded_keywords.as_ref()));
}
impl<K: Ord> SearchIndex<K> {
#[inline]
pub(crate) fn string_keywords(
&self,
string: &str,
context: &SplitContext
) -> Vec<KString> {
let string = KString::from(self.normalize(string).into_owned());
let mut keywords: Vec<KString> = self.split_pattern
.as_ref()
.map(|split_pattern| string
.split(split_pattern.as_slice())
.filter(|keyword| {
let chars = keyword.chars().count();
chars >= self.minimum_keyword_length
&& chars <= self.maximum_keyword_length
}) .filter(|keyword| !exclude_keyword(keyword, self.exclude_keywords.as_ref()))
.map(KString::from_ref)
.collect()
) .unwrap_or_default();
let chars = string.chars().count();
if context == &SplitContext::Searching
&& self.split_pattern.is_none()
&& chars >= self.minimum_keyword_length
{
keywords = vec![string];
} else if let Some(maximum_string_length) = self.maximum_string_length {
if context == &SplitContext::Indexing
&& chars >= self.minimum_keyword_length
&& chars <= maximum_string_length
&& !exclude_keyword(&string, self.exclude_keywords.as_ref())
{
keywords.push(string);
} }
keywords
} }