use crate::ci_engine;
use alphanumeric::CharType;
pub trait SimpleMatch {
fn equals_ci(&self, pattern: &str) -> bool;
fn equals_ci_alphanum(&self, pattern: &str) -> bool;
fn starts_with_ci(&self, pattern: &str) -> bool;
fn starts_with_ci_alphanum(&self, pattern: &str) -> bool;
fn ends_with_ci(&self, pattern: &str) -> bool;
fn ends_with_ci_alphanum(&self, pattern: &str) -> bool;
fn contains_ci(&self, pattern: &str) -> bool;
fn contains_ci_alphanum(&self, pattern: &str) -> bool;
}
impl<T: AsRef<str>> SimpleMatch for T {
fn equals_ci(&self, pattern: &str) -> bool {
ci_engine::ci_eq(self.as_ref(), pattern)
}
fn equals_ci_alphanum(&self, pattern: &str) -> bool {
ci_engine::ci_alphanum_eq(self.as_ref(), pattern)
}
fn starts_with_ci(&self, pattern: &str) -> bool {
ci_engine::ci_starts_with(self.as_ref(), pattern)
}
fn starts_with_ci_alphanum(&self, pattern: &str) -> bool {
ci_engine::ci_alphanum_starts_with(self.as_ref(), pattern)
}
fn ends_with_ci(&self, pattern: &str) -> bool {
ci_engine::ci_ends_with(self.as_ref(), pattern)
}
fn ends_with_ci_alphanum(&self, pattern: &str) -> bool {
ci_engine::ci_alphanum_ends_with(self.as_ref(), pattern)
}
fn contains_ci(&self, pattern: &str) -> bool {
ci_engine::ci_contains(self.as_ref(), pattern)
}
fn contains_ci_alphanum(&self, pattern: &str) -> bool {
ci_engine::ci_alphanum_contains(self.as_ref(), pattern)
}
}
pub trait MatchOccurrences {
fn find_matched_indices(&self, pat: &str) -> Vec<usize>;
fn find_char_indices(&self, pat: char) -> Vec<usize>;
}
impl<T: AsRef<str>> MatchOccurrences for T {
fn find_matched_indices(&self, pat: &str) -> Vec<usize> {
self.as_ref()
.match_indices(pat)
.into_iter()
.map(|pair| pair.0)
.collect::<Vec<usize>>()
}
fn find_char_indices(&self, pat: char) -> Vec<usize> {
self.as_ref()
.match_indices(pat)
.into_iter()
.map(|pair| pair.0)
.collect::<Vec<usize>>()
}
}
pub trait SimplContainsType
where
Self: SimpleMatch,
{
fn contains_type(&self, char_type: CharType) -> bool;
fn contains_types(&self, char_types: &[CharType]) -> bool;
fn starts_with_type(&self, char_type: CharType) -> bool;
fn starts_with_types(&self, char_types: &[CharType]) -> bool;
fn ends_with_type(&self, char_type: CharType) -> bool;
fn ends_with_types(&self, char_types: &[CharType]) -> bool;
}
impl<T: AsRef<str>> SimplContainsType for T {
fn contains_type(&self, char_type: CharType) -> bool {
self.as_ref().chars().any(|ch| char_type.is_in_range(&ch))
}
fn contains_types(&self, char_types: &[CharType]) -> bool {
self.as_ref()
.chars()
.any(|ch| char_types.into_iter().any(|ct| ct.is_in_range(&ch)))
}
fn starts_with_type(&self, char_type: CharType) -> bool {
if let Some(first) = self.as_ref().chars().nth(0) {
char_type.is_in_range(&first)
} else {
false
}
}
fn starts_with_types(&self, char_types: &[CharType]) -> bool {
if let Some(first) = self.as_ref().chars().nth(0) {
char_types.into_iter().any(|ct| ct.is_in_range(&first))
} else {
false
}
}
fn ends_with_type(&self, char_type: CharType) -> bool {
if let Some(first) = self.as_ref().chars().last() {
char_type.is_in_range(&first)
} else {
false
}
}
fn ends_with_types(&self, char_types: &[CharType]) -> bool {
if let Some(first) = self.as_ref().chars().last() {
char_types.into_iter().any(|ct| ct.is_in_range(&first))
} else {
false
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_equals_ci() {
assert!("Hello World".equals_ci("hello world"));
assert!("RUST".equals_ci("rust"));
assert!(!"Hello".equals_ci("World"));
assert!("".equals_ci(""));
}
#[test]
fn test_equals_ci_alphanum() {
assert!("Start-Up".equals_ci_alphanum("startup"));
assert!("hello---world".equals_ci_alphanum("HELLOWORLD"));
assert!(!"abc".equals_ci_alphanum("xyz"));
}
#[test]
fn test_starts_with_ci() {
assert!("Hello World".starts_with_ci("hello"));
assert!("Hello World".starts_with_ci("HELLO"));
assert!(!"Hello World".starts_with_ci("world"));
assert!("Hello".starts_with_ci(""));
}
#[test]
fn test_starts_with_ci_alphanum() {
assert!("_Cat-image".starts_with_ci_alphanum("cat"));
assert!("---Hello!!!".starts_with_ci_alphanum("hello"));
assert!(!"Dog-photo".starts_with_ci_alphanum("cat"));
}
#[test]
fn test_ends_with_ci() {
assert!("Hello World".ends_with_ci("WORLD"));
assert!("photo.JPG".ends_with_ci(".jpg"));
assert!(!"photo.png".ends_with_ci(".jpg"));
assert!("Hello".ends_with_ci(""));
}
#[test]
fn test_ends_with_ci_alphanum() {
assert!("photo-file.JPG!!!".ends_with_ci_alphanum("jpg"));
assert!("data---CSV".ends_with_ci_alphanum("csv"));
assert!(!"photo.png".ends_with_ci_alphanum("jpg"));
}
#[test]
fn test_contains_ci() {
assert!("Hello World".contains_ci("LO WO"));
assert!("ABCDEF".contains_ci("cde"));
assert!(!"Hello".contains_ci("xyz"));
assert!("Hello".contains_ci(""));
}
#[test]
fn test_contains_ci_alphanum() {
assert!("He--llo Wo!!rld".contains_ci_alphanum("lloworld"));
assert!("a-b-c-d".contains_ci_alphanum("ABCD"));
assert!(!"Hello".contains_ci_alphanum("xyz"));
}
#[test]
fn test_find_matched_indices() {
assert_eq!("abcabc".find_matched_indices("bc"), vec![1, 4]);
assert_eq!("hello".find_matched_indices("ll"), vec![2]);
assert_eq!("hello".find_matched_indices("xyz"), vec![]);
assert_eq!("aaa".find_matched_indices("a"), vec![0, 1, 2]);
}
#[test]
fn test_find_char_indices() {
assert_eq!("a.b.c".find_char_indices('.'), vec![1, 3]);
assert_eq!("hello".find_char_indices('l'), vec![2, 3]);
assert_eq!("hello".find_char_indices('z'), vec![]);
}
#[test]
fn test_contains_type() {
assert!("abc123".contains_type(CharType::DecDigit));
assert!(!"abcdef".contains_type(CharType::DecDigit));
assert!("Hello World".contains_type(CharType::Spaces));
assert!(!"HelloWorld".contains_type(CharType::Spaces));
assert!("hello!".contains_type(CharType::Punctuation));
}
#[test]
fn test_contains_types() {
assert!("abc".contains_types(&[CharType::DecDigit, CharType::Alpha]));
assert!(!"123".contains_types(&[CharType::Alpha, CharType::Spaces]));
assert!("hello world".contains_types(&[CharType::Spaces, CharType::Upper]));
}
#[test]
fn test_starts_with_type() {
assert!("123abc".starts_with_type(CharType::DecDigit));
assert!(!"abc123".starts_with_type(CharType::DecDigit));
assert!("Hello".starts_with_type(CharType::Upper));
assert!(!"hello".starts_with_type(CharType::Upper));
assert!(!("".starts_with_type(CharType::Alpha)));
}
#[test]
fn test_starts_with_types() {
assert!("Hello".starts_with_types(&[CharType::Upper, CharType::DecDigit]));
assert!("9lives".starts_with_types(&[CharType::Upper, CharType::DecDigit]));
assert!(!"hello".starts_with_types(&[CharType::Upper, CharType::DecDigit]));
assert!(!("".starts_with_types(&[CharType::Alpha])));
}
#[test]
fn test_ends_with_type() {
assert!("abc9".ends_with_type(CharType::DecDigit));
assert!(!"abc".ends_with_type(CharType::DecDigit));
assert!("hellO".ends_with_type(CharType::Upper));
assert!(!("".ends_with_type(CharType::Alpha)));
}
#[test]
fn test_ends_with_types() {
assert!("hello!".ends_with_types(&[CharType::Punctuation, CharType::DecDigit]));
assert!("test9".ends_with_types(&[CharType::Punctuation, CharType::DecDigit]));
assert!(!"hello".ends_with_types(&[CharType::Punctuation, CharType::DecDigit]));
assert!(!("".ends_with_types(&[CharType::Alpha])));
}
}