use std::borrow::Cow;
use crate::ranking::{Ranking, get_match_ranking};
pub trait AsMatchStr {
fn as_match_str(&self) -> &str;
}
impl AsMatchStr for String {
fn as_match_str(&self) -> &str {
self.as_str()
}
}
impl AsMatchStr for str {
fn as_match_str(&self) -> &str {
self
}
}
impl AsMatchStr for &str {
fn as_match_str(&self) -> &str {
self
}
}
impl AsMatchStr for Cow<'_, str> {
fn as_match_str(&self) -> &str {
self.as_ref()
}
}
pub fn rank_item<T: AsMatchStr>(item: &T, query: &str, keep_diacritics: bool) -> Ranking {
get_match_ranking(item.as_match_str(), query, keep_diacritics)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn as_match_str_string() {
let s = String::from("hello");
assert_eq!(s.as_match_str(), "hello");
}
#[test]
fn as_match_str_str_ref() {
let s: &str = "world";
assert_eq!(s.as_match_str(), "world");
}
#[test]
fn as_match_str_cow_borrowed() {
let cow: Cow<'_, str> = Cow::Borrowed("borrowed");
assert_eq!(cow.as_match_str(), "borrowed");
}
#[test]
fn as_match_str_cow_owned() {
let cow: Cow<'_, str> = Cow::Owned("owned".to_owned());
assert_eq!(cow.as_match_str(), "owned");
}
#[test]
fn as_match_str_empty_string() {
let s = String::new();
assert_eq!(s.as_match_str(), "");
}
#[test]
fn as_match_str_empty_str() {
let s: &str = "";
assert_eq!(s.as_match_str(), "");
}
#[test]
fn rank_string_case_sensitive_equal() {
let item = String::from("Green");
assert_eq!(
rank_item(&item, "Green", false),
Ranking::CaseSensitiveEqual
);
}
#[test]
fn rank_string_equal() {
let item = String::from("Green");
assert_eq!(rank_item(&item, "green", false), Ranking::Equal);
}
#[test]
fn rank_string_starts_with() {
let item = String::from("Greenland");
assert_eq!(rank_item(&item, "green", false), Ranking::StartsWith);
}
#[test]
fn rank_string_word_starts_with() {
let item = String::from("San Francisco");
assert_eq!(rank_item(&item, "fran", false), Ranking::WordStartsWith);
}
#[test]
fn rank_string_contains() {
let item = String::from("abcdef");
assert_eq!(rank_item(&item, "cde", false), Ranking::Contains);
}
#[test]
fn rank_string_acronym() {
let item = String::from("North-West Airlines");
assert_eq!(rank_item(&item, "nwa", false), Ranking::Acronym);
}
#[test]
fn rank_string_fuzzy_matches() {
let item = String::from("playground");
let rank = rank_item(&item, "plgnd", false);
match rank {
Ranking::Matches(s) => {
assert!(
s > 1.0 && s < 2.0,
"expected sub-score in (1.0, 2.0), got {s}"
);
}
other => panic!("expected Matches, got {other:?}"),
}
}
#[test]
fn rank_string_no_match() {
let item = String::from("abc");
assert_eq!(rank_item(&item, "xyz", false), Ranking::NoMatch);
}
#[test]
fn rank_string_diacritics_stripped() {
let item = String::from("caf\u{00e9}");
assert_eq!(rank_item(&item, "cafe", false), Ranking::CaseSensitiveEqual);
}
#[test]
fn rank_string_diacritics_kept() {
let item = String::from("caf\u{00e9}");
assert_eq!(rank_item(&item, "cafe", true), Ranking::NoMatch);
}
#[test]
fn rank_str_case_sensitive_equal() {
let item: &str = "Green";
assert_eq!(
rank_item(&item, "Green", false),
Ranking::CaseSensitiveEqual
);
}
#[test]
fn rank_str_equal() {
let item: &str = "Green";
assert_eq!(rank_item(&item, "green", false), Ranking::Equal);
}
#[test]
fn rank_str_starts_with() {
let item: &str = "Greenland";
assert_eq!(rank_item(&item, "green", false), Ranking::StartsWith);
}
#[test]
fn rank_str_word_starts_with() {
let item: &str = "San Francisco";
assert_eq!(rank_item(&item, "fran", false), Ranking::WordStartsWith);
}
#[test]
fn rank_str_contains() {
let item: &str = "abcdef";
assert_eq!(rank_item(&item, "cde", false), Ranking::Contains);
}
#[test]
fn rank_str_acronym() {
let item: &str = "North-West Airlines";
assert_eq!(rank_item(&item, "nwa", false), Ranking::Acronym);
}
#[test]
fn rank_str_fuzzy_matches() {
let item: &str = "playground";
let rank = rank_item(&item, "plgnd", false);
match rank {
Ranking::Matches(s) => {
assert!(
s > 1.0 && s < 2.0,
"expected sub-score in (1.0, 2.0), got {s}"
);
}
other => panic!("expected Matches, got {other:?}"),
}
}
#[test]
fn rank_str_no_match() {
let item: &str = "abc";
assert_eq!(rank_item(&item, "xyz", false), Ranking::NoMatch);
}
#[test]
fn rank_cow_borrowed() {
let item: Cow<'_, str> = Cow::Borrowed("Green");
assert_eq!(
rank_item(&item, "Green", false),
Ranking::CaseSensitiveEqual
);
}
#[test]
fn rank_cow_owned() {
let item: Cow<'_, str> = Cow::Owned("Greenland".to_owned());
assert_eq!(rank_item(&item, "green", false), Ranking::StartsWith);
}
#[test]
fn rank_empty_item_empty_query() {
let item = String::new();
assert_eq!(rank_item(&item, "", false), Ranking::CaseSensitiveEqual);
}
#[test]
fn rank_empty_query_nonempty_item() {
let item = String::from("anything");
assert_eq!(rank_item(&item, "", false), Ranking::StartsWith);
}
#[test]
fn rank_query_longer_than_item() {
let item = String::from("ab");
assert_eq!(rank_item(&item, "abcdef", false), Ranking::NoMatch);
}
#[test]
fn rank_item_matches_get_match_ranking_for_string() {
let item = String::from("San Francisco");
let via_rank_item = rank_item(&item, "fran", false);
let via_direct = get_match_ranking("San Francisco", "fran", false);
assert_eq!(via_rank_item, via_direct);
}
#[test]
fn rank_item_matches_get_match_ranking_for_str() {
let item: &str = "playground";
let via_rank_item = rank_item(&item, "plgnd", false);
let via_direct = get_match_ranking("playground", "plgnd", false);
assert_eq!(via_rank_item, via_direct);
}
}