pub trait StringChecks {
#[must_use]
fn is_blank(&self) -> bool;
#[must_use]
fn is_not_blank(&self) -> bool;
#[must_use]
fn is_numeric(&self) -> bool;
#[must_use]
fn is_numeric_space(&self) -> bool;
#[must_use]
fn is_alpha(&self) -> bool;
#[must_use]
fn is_alpha_space(&self) -> bool;
#[must_use]
fn is_alphanumeric(&self) -> bool;
#[must_use]
fn is_alphanumeric_space(&self) -> bool;
#[must_use]
fn is_whitespace(&self) -> bool;
#[must_use]
fn is_ascii_printable(&self) -> bool;
#[must_use]
fn is_all_lowercase(&self) -> bool;
#[must_use]
fn is_all_uppercase(&self) -> bool;
#[must_use]
fn is_mixed_case(&self) -> bool;
}
impl StringChecks for str {
fn is_blank(&self) -> bool {
self.chars().all(|c| c.is_whitespace())
}
fn is_not_blank(&self) -> bool {
!self.is_blank()
}
fn is_numeric(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_numeric())
}
fn is_numeric_space(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_numeric() || c.is_whitespace())
}
fn is_alpha(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_alphabetic())
}
fn is_alpha_space(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_alphabetic() || c.is_whitespace())
}
fn is_alphanumeric(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_alphanumeric())
}
fn is_alphanumeric_space(&self) -> bool {
!self.is_empty()
&& self
.chars()
.all(|c| c.is_alphanumeric() || c.is_whitespace())
}
fn is_whitespace(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_whitespace())
}
fn is_ascii_printable(&self) -> bool {
self.chars()
.all(|c| c.is_ascii() && (32..=126).contains(&(c as u32)))
}
fn is_all_lowercase(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_lowercase())
}
fn is_all_uppercase(&self) -> bool {
!self.is_empty() && self.chars().all(|c| c.is_uppercase())
}
fn is_mixed_case(&self) -> bool {
let has_upper = self.chars().any(|c| c.is_uppercase());
let has_lower = self.chars().any(|c| c.is_lowercase());
has_upper && has_lower
}
}
#[cfg(test)]
mod tests {
use super::*;
fn whitespace() -> String {
let mut ws = String::new();
for i in 0..=u16::MAX {
if let Some(c) = char::from_u32(i as u32) {
if c.is_whitespace() {
ws.push(c);
}
}
}
ws
}
mod is_blank {
use super::*;
#[test]
fn empty_string() {
assert!("".is_blank());
}
#[test]
fn whitespace_only() {
assert!(whitespace().is_blank());
}
#[test]
fn single_space() {
assert!(" ".is_blank());
}
#[test]
fn multiple_spaces() {
assert!(" ".is_blank());
}
#[test]
fn tab() {
assert!("\t".is_blank());
}
#[test]
fn newline() {
assert!("\n".is_blank());
}
#[test]
fn carriage_return() {
assert!("\r".is_blank());
}
#[test]
fn mixed_whitespace() {
assert!(" \t\n\r ".is_blank());
}
#[test]
fn single_char() {
assert!(!"a".is_blank());
}
#[test]
fn word() {
assert!(!"foo".is_blank());
}
#[test]
fn word_with_surrounding_spaces() {
assert!(!" foo ".is_blank());
}
}
mod is_not_blank {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_not_blank());
}
#[test]
fn whitespace_only() {
assert!(!whitespace().is_not_blank());
}
#[test]
fn single_char() {
assert!("a".is_not_blank());
}
#[test]
fn word() {
assert!("foo".is_not_blank());
}
#[test]
fn word_with_surrounding_spaces() {
assert!(" foo ".is_not_blank());
}
}
mod is_numeric {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_numeric());
}
#[test]
fn whitespace() {
assert!(!" ".is_numeric());
}
#[test]
fn simple_digits() {
assert!("123".is_numeric());
}
#[test]
fn single_digit() {
assert!("0".is_numeric());
}
#[test]
fn hindi_digits() {
assert!("\u{0967}\u{0968}\u{0969}".is_numeric());
}
#[test]
fn arabic_indic_digits() {
assert!("\u{0660}\u{0661}\u{0662}".is_numeric());
}
#[test]
fn digits_with_space() {
assert!(!"12 3".is_numeric());
}
#[test]
fn letters_and_digits() {
assert!(!"ab2c".is_numeric());
}
#[test]
fn digits_with_hyphen() {
assert!(!"12-3".is_numeric());
}
#[test]
fn decimal_number() {
assert!(!"12.3".is_numeric());
}
#[test]
fn negative_number() {
assert!(!"-123".is_numeric());
}
#[test]
fn positive_number() {
assert!(!"+123".is_numeric());
}
#[test]
fn only_letters() {
assert!(!"abc".is_numeric());
}
}
mod is_numeric_space {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_numeric_space());
}
#[test]
fn spaces_only() {
assert!(" ".is_numeric_space());
}
#[test]
fn simple_digits() {
assert!("123".is_numeric_space());
}
#[test]
fn digits_with_space() {
assert!("12 3".is_numeric_space());
}
#[test]
fn space_then_digits() {
assert!(" 123".is_numeric_space());
}
#[test]
fn digits_then_space() {
assert!("123 ".is_numeric_space());
}
#[test]
fn letters_and_digits() {
assert!(!"ab2c".is_numeric_space());
}
#[test]
fn decimal_number() {
assert!(!"12.3".is_numeric_space());
}
}
mod is_alpha {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_alpha());
}
#[test]
fn whitespace() {
assert!(!" ".is_alpha());
}
#[test]
fn lowercase_letters() {
assert!("abc".is_alpha());
}
#[test]
fn uppercase_letters() {
assert!("ABC".is_alpha());
}
#[test]
fn mixed_case_letters() {
assert!("aBc".is_alpha());
}
#[test]
fn letters_with_space() {
assert!(!"ab c".is_alpha());
}
#[test]
fn letters_with_digit() {
assert!(!"ab2c".is_alpha());
}
#[test]
fn letters_with_hyphen() {
assert!(!"ab-c".is_alpha());
}
#[test]
fn only_digits() {
assert!(!"123".is_alpha());
}
}
mod is_alpha_space {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_alpha_space());
}
#[test]
fn spaces_only() {
assert!(" ".is_alpha_space());
}
#[test]
fn lowercase_letters() {
assert!("abc".is_alpha_space());
}
#[test]
fn letters_with_space() {
assert!("ab c".is_alpha_space());
}
#[test]
fn letters_with_digit() {
assert!(!"ab2c".is_alpha_space());
}
#[test]
fn letters_with_hyphen() {
assert!(!"ab-c".is_alpha_space());
}
}
mod is_alphanumeric {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_alphanumeric());
}
#[test]
fn whitespace() {
assert!(!" ".is_alphanumeric());
}
#[test]
fn lowercase_letters() {
assert!("abc".is_alphanumeric());
}
#[test]
fn letters_with_space() {
assert!(!"ab c".is_alphanumeric());
}
#[test]
fn letters_and_digits() {
assert!("ab2c".is_alphanumeric());
}
#[test]
fn only_digits() {
assert!("123".is_alphanumeric());
}
#[test]
fn letters_with_hyphen() {
assert!(!"ab-c".is_alphanumeric());
}
#[test]
fn letters_with_underscore() {
assert!(!"ab_c".is_alphanumeric());
}
}
mod is_alphanumeric_space {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_alphanumeric_space());
}
#[test]
fn spaces_only() {
assert!(" ".is_alphanumeric_space());
}
#[test]
fn lowercase_letters() {
assert!("abc".is_alphanumeric_space());
}
#[test]
fn letters_with_space() {
assert!("ab c".is_alphanumeric_space());
}
#[test]
fn letters_and_digits() {
assert!("ab2c".is_alphanumeric_space());
}
#[test]
fn letters_digits_and_space() {
assert!("ab 2c".is_alphanumeric_space());
}
#[test]
fn letters_with_hyphen() {
assert!(!"ab-c".is_alphanumeric_space());
}
}
mod is_whitespace {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_whitespace());
}
#[test]
fn spaces_only() {
assert!(" ".is_whitespace());
}
#[test]
fn tab() {
assert!("\t".is_whitespace());
}
#[test]
fn newline() {
assert!("\n".is_whitespace());
}
#[test]
fn carriage_return() {
assert!("\r".is_whitespace());
}
#[test]
fn mixed_whitespace() {
assert!(" \t\n\r ".is_whitespace());
}
#[test]
fn letters() {
assert!(!"abc".is_whitespace());
}
#[test]
fn letters_and_digits() {
assert!(!"ab2c".is_whitespace());
}
#[test]
fn letters_with_hyphen() {
assert!(!"ab-c".is_whitespace());
}
#[test]
fn space_with_letter() {
assert!(!" a".is_whitespace());
}
}
mod is_ascii_printable {
use super::*;
#[test]
fn empty_string() {
assert!("".is_ascii_printable());
}
#[test]
fn space() {
assert!(" ".is_ascii_printable());
}
#[test]
fn lowercase_letters() {
assert!("abc".is_ascii_printable());
}
#[test]
fn letters_and_digits() {
assert!("abc123".is_ascii_printable());
}
#[test]
fn special_characters() {
assert!("!@#$%^&*()".is_ascii_printable());
}
#[test]
fn printable_range_boundary_low() {
assert!(" ".is_ascii_printable());
}
#[test]
fn printable_range_boundary_high() {
assert!("~".is_ascii_printable());
}
#[test]
fn non_ascii_characters() {
assert!(!"Jocelyn N'takpé".is_ascii_printable());
}
#[test]
fn tab_not_printable() {
assert!(!"ab\t".is_ascii_printable());
}
#[test]
fn newline_not_printable() {
assert!(!"ab\n".is_ascii_printable());
}
#[test]
fn control_char_below_space() {
assert!(!"\x1F".is_ascii_printable());
}
#[test]
fn del_character() {
assert!(!"\x7F".is_ascii_printable());
}
#[test]
fn extended_ascii() {
assert!(!"\u{0080}".is_ascii_printable());
}
}
mod is_all_lowercase {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_all_lowercase());
}
#[test]
fn whitespace() {
assert!(!" ".is_all_lowercase());
}
#[test]
fn lowercase_letters() {
assert!("abc".is_all_lowercase());
}
#[test]
fn lowercase_with_trailing_space() {
assert!(!"abc ".is_all_lowercase());
}
#[test]
fn lowercase_with_newline() {
assert!(!"abc\n".is_all_lowercase());
}
#[test]
fn mixed_case() {
assert!(!"abC".is_all_lowercase());
}
#[test]
fn lowercase_with_space() {
assert!(!"ab c".is_all_lowercase());
}
#[test]
fn lowercase_with_digit() {
assert!(!"ab1c".is_all_lowercase());
}
#[test]
fn lowercase_with_slash() {
assert!(!"ab/c".is_all_lowercase());
}
}
mod is_all_uppercase {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_all_uppercase());
}
#[test]
fn whitespace() {
assert!(!" ".is_all_uppercase());
}
#[test]
fn uppercase_letters() {
assert!("ABC".is_all_uppercase());
}
#[test]
fn uppercase_with_trailing_space() {
assert!(!"ABC ".is_all_uppercase());
}
#[test]
fn uppercase_with_newline() {
assert!(!"ABC\n".is_all_uppercase());
}
#[test]
fn mixed_case() {
assert!(!"aBC".is_all_uppercase());
}
#[test]
fn uppercase_with_space() {
assert!(!"A C".is_all_uppercase());
}
#[test]
fn uppercase_with_digit() {
assert!(!"A1C".is_all_uppercase());
}
#[test]
fn uppercase_with_slash() {
assert!(!"A/C".is_all_uppercase());
}
}
mod is_mixed_case {
use super::*;
#[test]
fn empty_string() {
assert!(!"".is_mixed_case());
}
#[test]
fn whitespace() {
assert!(!" ".is_mixed_case());
}
#[test]
fn single_uppercase() {
assert!(!"A".is_mixed_case());
}
#[test]
fn single_lowercase() {
assert!(!"a".is_mixed_case());
}
#[test]
fn single_slash() {
assert!(!"/".is_mixed_case());
}
#[test]
fn uppercase_with_slash() {
assert!(!"A/".is_mixed_case());
}
#[test]
fn slash_with_lowercase() {
assert!(!"/b".is_mixed_case());
}
#[test]
fn all_lowercase() {
assert!(!"abc".is_mixed_case());
}
#[test]
fn all_uppercase() {
assert!(!"ABC".is_mixed_case());
}
#[test]
fn mixed_case() {
assert!("aBc".is_mixed_case());
}
#[test]
fn mixed_case_with_trailing_space() {
assert!("aBc ".is_mixed_case());
}
#[test]
fn uppercase_space_lowercase() {
assert!("A c".is_mixed_case());
}
#[test]
fn mixed_case_with_newline() {
assert!("aBc\n".is_mixed_case());
}
#[test]
fn uppercase_digit_lowercase() {
assert!("A1c".is_mixed_case());
}
#[test]
fn lowercase_slash_uppercase() {
assert!("a/C".is_mixed_case());
}
}
mod string_types {
use super::*;
#[test]
fn string_type() {
assert!(String::new().is_blank());
assert!(!String::from("hello").is_blank());
}
#[test]
fn string_ref() {
let s = String::from("hello");
assert!(!s.is_blank());
}
#[test]
fn boxed_str() {
let s: Box<str> = "hello".into();
assert!(!s.is_blank());
}
}
}