use crate::guard_empty;
pub trait StringContains {
#[must_use]
fn contains_any_char(&self, search_chars: &[char]) -> bool;
#[must_use]
fn contains_any_in(&self, search_chars: &str) -> bool;
#[must_use]
fn contains_any(&self, search: &[&str]) -> bool;
#[must_use]
fn contains_ignore_case(&self, search: &str) -> bool;
#[must_use]
fn contains_any_ignore_case(&self, search: &[&str]) -> bool;
#[must_use]
fn contains_none_char(&self, invalid_chars: &[char]) -> bool;
#[must_use]
fn contains_none(&self, invalid_chars: &str) -> bool;
#[must_use]
fn contains_only_char(&self, valid_chars: &[char]) -> bool;
#[must_use]
fn contains_only(&self, valid_chars: &str) -> bool;
#[must_use]
fn contains_whitespace(&self) -> bool;
}
impl StringContains for str {
fn contains_any_char(&self, search_chars: &[char]) -> bool {
guard_empty!(self, search_chars, false);
self.chars().any(|c| search_chars.contains(&c))
}
fn contains_any_in(&self, search_chars: &str) -> bool {
guard_empty!(self, search_chars, false);
self.chars().any(|c| search_chars.chars().any(|sc| sc == c))
}
fn contains_any(&self, search: &[&str]) -> bool {
guard_empty!(self, search, false);
search.iter().any(|s| !s.is_empty() && self.contains(s))
}
fn contains_ignore_case(&self, search: &str) -> bool {
guard_empty!(self, search, false);
self.to_lowercase().contains(&search.to_lowercase())
}
fn contains_any_ignore_case(&self, search: &[&str]) -> bool {
guard_empty!(self, search, false);
let lower = self.to_lowercase();
search
.iter()
.any(|s| !s.is_empty() && lower.contains(&s.to_lowercase()))
}
fn contains_none_char(&self, invalid_chars: &[char]) -> bool {
guard_empty!(self, invalid_chars, true);
!self.chars().any(|c| invalid_chars.contains(&c))
}
fn contains_none(&self, invalid_chars: &str) -> bool {
guard_empty!(self, invalid_chars, true);
!self
.chars()
.any(|c| invalid_chars.chars().any(|ic| ic == c))
}
fn contains_only_char(&self, valid_chars: &[char]) -> bool {
guard_empty!(self, valid_chars, false);
self.chars().all(|c| valid_chars.contains(&c))
}
fn contains_only(&self, valid_chars: &str) -> bool {
guard_empty!(self, valid_chars, false);
self.chars().all(|c| valid_chars.chars().any(|vc| vc == c))
}
fn contains_whitespace(&self) -> bool {
self.chars().any(|c| c.is_whitespace())
}
}
#[cfg(test)]
mod tests {
use super::*;
mod contains_any_char {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_any_char(&['a', 'b']));
}
#[test]
fn empty_search() {
assert!(!"abc".contains_any_char(&[]));
}
#[test]
fn both_empty() {
assert!(!"".contains_any_char(&[]));
}
#[test]
fn found_first_char() {
assert!("zzabyycdxx".contains_any_char(&['z', 'a']));
}
#[test]
fn found_middle_char() {
assert!("zzabyycdxx".contains_any_char(&['b', 'y']));
}
#[test]
fn found_multiple() {
assert!("zzabyycdxx".contains_any_char(&['z', 'y']));
}
#[test]
fn not_found() {
assert!(!"aba".contains_any_char(&['z']));
}
#[test]
fn unicode() {
assert!("日本語".contains_any_char(&['本', 'x']));
assert!(!"日本語".contains_any_char(&['x', 'y']));
}
}
mod contains_any_in {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_any_in("ab"));
}
#[test]
fn empty_search() {
assert!(!"abc".contains_any_in(""));
}
#[test]
fn both_empty() {
assert!(!"".contains_any_in(""));
}
#[test]
fn found() {
assert!("zzabyycdxx".contains_any_in("za"));
}
#[test]
fn found_middle() {
assert!("zzabyycdxx".contains_any_in("by"));
}
#[test]
fn not_found() {
assert!(!"aba".contains_any_in("z"));
}
#[test]
fn unicode() {
assert!("日本語".contains_any_in("本x"));
assert!(!"日本語".contains_any_in("xy"));
}
}
mod contains_any {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_any(&["ab", "cd"]));
}
#[test]
fn empty_search() {
assert!(!"abc".contains_any(&[]));
}
#[test]
fn both_empty() {
assert!(!"".contains_any(&[]));
}
#[test]
fn found_first() {
assert!("abcd".contains_any(&["ab", "cd"]));
}
#[test]
fn found_second() {
assert!("abcd".contains_any(&["xy", "cd"]));
}
#[test]
fn not_found() {
assert!(!"abcd".contains_any(&["xy", "zz"]));
}
#[test]
fn empty_search_string() {
assert!(!"abc".contains_any(&[""]));
assert!("abc".contains_any(&["", "b"]));
}
#[test]
fn unicode() {
assert!("日本語".contains_any(&["本", "x"]));
assert!(!"日本語".contains_any(&["x", "y"]));
}
#[test]
fn with_empty_string_in_array() {
assert!("abcd".contains_any(&["ab", ""]));
}
#[test]
fn case_sensitive() {
assert!(!"hello, goodbye".contains_any(&["Hello", "Goodbye"]));
}
}
mod contains_ignore_case {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_ignore_case("a"));
}
#[test]
fn empty_search() {
assert!(!"abc".contains_ignore_case(""));
}
#[test]
fn both_empty() {
assert!(!"".contains_ignore_case(""));
}
#[test]
fn found_lower_in_lower() {
assert!("abc".contains_ignore_case("a"));
}
#[test]
fn found_upper_in_lower() {
assert!("abc".contains_ignore_case("A"));
}
#[test]
fn found_lower_in_upper() {
assert!("ABC".contains_ignore_case("a"));
}
#[test]
fn found_mixed() {
assert!("abc".contains_ignore_case("ABC"));
assert!("ABC".contains_ignore_case("abc"));
assert!("AbCdEf".contains_ignore_case("cDe"));
}
#[test]
fn not_found() {
assert!(!"abc".contains_ignore_case("Z"));
}
#[test]
fn unicode() {
assert!("Héllo".contains_ignore_case("héllo"));
assert!("HÉLLO".contains_ignore_case("héllo"));
}
}
mod contains_any_ignore_case {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_any_ignore_case(&["ab"]));
}
#[test]
fn empty_search() {
assert!(!"abc".contains_any_ignore_case(&[]));
}
#[test]
fn found() {
assert!("abcd".contains_any_ignore_case(&["AB", "cd"]));
}
#[test]
fn found_second() {
assert!("abc".contains_any_ignore_case(&["D", "ABC"]));
}
#[test]
fn not_found() {
assert!(!"abc".contains_any_ignore_case(&["D", "XYZ"]));
}
#[test]
fn empty_search_string() {
assert!(!"abc".contains_any_ignore_case(&[""]));
}
#[test]
fn hello_goodbye_both_lowercase() {
assert!("hello, goodbye".contains_any_ignore_case(&["hello", "goodbye"]));
}
#[test]
fn hello_goodbye_mixed_case() {
assert!("hello, goodbye".contains_any_ignore_case(&["hello", "Goodbye"]));
}
#[test]
fn hello_goodbye_both_capitalized() {
assert!("hello, goodbye".contains_any_ignore_case(&["Hello", "Goodbye"]));
}
}
mod contains_none_char {
use super::*;
#[test]
fn empty_string() {
assert!("".contains_none_char(&['a', 'b']));
}
#[test]
fn empty_invalid() {
assert!("abc".contains_none_char(&[]));
}
#[test]
fn both_empty() {
assert!("".contains_none_char(&[]));
}
#[test]
fn none_found() {
assert!("abab".contains_none_char(&['x', 'y', 'z']));
}
#[test]
fn found_first() {
assert!(!"abab".contains_none_char(&['a', 'b', 'z']));
}
#[test]
fn found_last() {
assert!(!"abab".contains_none_char(&['x', 'y', 'z', 'a']));
}
#[test]
fn unicode() {
assert!("日本語".contains_none_char(&['x', 'y']));
assert!(!"日本語".contains_none_char(&['本', 'x']));
}
}
mod contains_none {
use super::*;
#[test]
fn empty_string() {
assert!("".contains_none("ab"));
}
#[test]
fn empty_invalid() {
assert!("abc".contains_none(""));
}
#[test]
fn both_empty() {
assert!("".contains_none(""));
}
#[test]
fn none_found() {
assert!("abab".contains_none("xyz"));
}
#[test]
fn found() {
assert!(!"abab".contains_none("abz"));
}
#[test]
fn found_partial() {
assert!(!"abz".contains_none("xyz"));
}
#[test]
fn unicode() {
assert!("日本語".contains_none("xy"));
assert!(!"日本語".contains_none("本x"));
}
#[test]
fn single_none() {
assert!("a".contains_none("b"));
}
#[test]
fn single_contains() {
assert!(!"a".contains_none("a"));
}
#[test]
fn single_contains_2() {
assert!(!"b".contains_none("b"));
}
#[test]
fn first_char_contained() {
assert!(!"ab".contains_none("a"));
}
#[test]
fn second_char_contained() {
assert!(!"ab".contains_none("b"));
}
}
mod contains_only_char {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_only_char(&['a', 'b']));
}
#[test]
fn empty_valid() {
assert!(!"abc".contains_only_char(&[]));
}
#[test]
fn both_empty() {
assert!(!"".contains_only_char(&[]));
}
#[test]
fn valid() {
assert!("ab".contains_only_char(&['a', 'b', 'c']));
}
#[test]
fn valid_repeated() {
assert!("abab".contains_only_char(&['a', 'b', 'c']));
}
#[test]
fn invalid_digit() {
assert!(!"ab1".contains_only_char(&['a', 'b', 'c']));
}
#[test]
fn invalid_char() {
assert!(!"abz".contains_only_char(&['a', 'b', 'c']));
}
#[test]
fn unicode() {
assert!("日本".contains_only_char(&['日', '本', '語']));
assert!(!"日本x".contains_only_char(&['日', '本', '語']));
}
}
mod contains_only {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_only("abc"));
}
#[test]
fn empty_valid() {
assert!(!"abc".contains_only(""));
}
#[test]
fn both_empty() {
assert!(!"".contains_only(""));
}
#[test]
fn valid() {
assert!("ab".contains_only("abc"));
}
#[test]
fn valid_repeated() {
assert!("abab".contains_only("abc"));
}
#[test]
fn invalid_digit() {
assert!(!"ab1".contains_only("abc"));
}
#[test]
fn invalid_char() {
assert!(!"abz".contains_only("abc"));
}
#[test]
fn unicode() {
assert!("日本".contains_only("日本語"));
assert!(!"日本x".contains_only("日本語"));
}
#[test]
fn does_contain_any() {
assert!(!"a".contains_only("b"));
}
#[test]
fn contains_single() {
assert!("a".contains_only("a"));
}
#[test]
fn contains_single_and_ignored() {
assert!("a".contains_only("ab"));
}
#[test]
fn equals() {
assert!("ab".contains_only("ab"));
}
}
mod contains_whitespace {
use super::*;
#[test]
fn empty_string() {
assert!(!"".contains_whitespace());
}
#[test]
fn only_spaces() {
assert!(" ".contains_whitespace());
}
#[test]
fn leading_space() {
assert!(" ab".contains_whitespace());
}
#[test]
fn trailing_space() {
assert!("ab ".contains_whitespace());
}
#[test]
fn middle_space() {
assert!("a b".contains_whitespace());
}
#[test]
fn tab() {
assert!("a\tb".contains_whitespace());
}
#[test]
fn newline() {
assert!("a\nb".contains_whitespace());
}
#[test]
fn carriage_return() {
assert!("a\rb".contains_whitespace());
}
#[test]
fn no_whitespace() {
assert!(!"abc".contains_whitespace());
}
#[test]
fn single_char_no_whitespace() {
assert!(!"a".contains_whitespace());
}
#[test]
fn trailing_tab() {
assert!("a\t".contains_whitespace());
}
#[test]
fn only_newline() {
assert!("\n".contains_whitespace());
}
#[test]
fn unicode_space() {
assert!("a\u{00A0}b".contains_whitespace());
}
}
mod string_types {
use super::*;
#[test]
fn string_type() {
assert!(String::from("abc").contains_any_char(&['a']));
}
#[test]
fn string_ref() {
let s = String::from("abc");
assert_eq!(s.contains_whitespace(), false);
}
#[test]
fn boxed_str() {
let s: Box<str> = "a b".into();
assert!(s.contains_whitespace());
}
}
}