use uuid::Uuid;
pub struct Str;
impl Str {
pub fn uc_first(s: &str) -> String {
let mut chars = s.chars();
match chars.next() {
None => String::new(),
Some(first_char) => first_char.to_uppercase().collect::<String>() + chars.as_str(),
}
}
pub fn uc_words(s: &str) -> String {
s.split_whitespace()
.map(Self::uc_first)
.collect::<Vec<_>>()
.join(" ")
}
#[cfg(feature = "regex")]
pub fn is_username_valid(name: String) -> Box<fancy_regex::Result<bool>> {
crate::helpers::regex::Tester::validate_username(&name)
}
pub fn uuid() -> String {
Uuid::new_v4().to_string().replace("-", "")
}
pub fn truncate(s: &str, max_length: usize) -> String {
if s.len() <= max_length {
s.to_string()
} else {
format!("{}...", &s[..max_length])
}
}
pub fn remove_whitespace(s: &str) -> String {
s.chars().filter(|c| !c.is_whitespace()).collect()
}
pub fn reverse(s: &str) -> String {
s.chars().rev().collect()
}
pub fn count_occurrences(s: &str, substr: &str) -> usize {
if substr.is_empty() {
return 0;
}
s.matches(substr).count()
}
pub fn is_numeric(s: &str) -> bool {
!s.is_empty() && s.chars().all(|c| c.is_ascii_digit())
}
pub fn is_alphabetic(s: &str) -> bool {
!s.is_empty() && s.chars().all(|c| c.is_alphabetic())
}
pub fn camel_case(s: &str) -> String {
let mut result = String::new();
let mut capitalize_next = false;
for (i, c) in s.chars().enumerate() {
if c == '_' {
capitalize_next = true;
} else if capitalize_next {
result.push(c.to_ascii_uppercase());
capitalize_next = false;
} else if i == 0 {
result.push(c.to_ascii_lowercase());
} else {
result.push(c);
}
}
result
}
pub fn pad_left(s: &str, width: usize, pad_char: char) -> String {
if s.len() >= width {
s.to_string()
} else {
format!("{}{}", pad_char.to_string().repeat(width - s.len()), s)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_uc_first() {
assert_eq!(Str::uc_first("hello"), "Hello");
assert_eq!(Str::uc_first("rust"), "Rust");
assert_eq!(Str::uc_first(""), ""); assert_eq!(Str::uc_first("a"), "A"); assert_eq!(Str::uc_first("hELLO"), "HELLO"); assert_eq!(Str::uc_first("1world"), "1world"); }
#[test]
fn test_uc_words() {
assert_eq!(Str::uc_words("hello world"), "Hello World");
assert_eq!(
Str::uc_words("rust programming language"),
"Rust Programming Language"
);
assert_eq!(Str::uc_words(""), ""); assert_eq!(Str::uc_words("a b c"), "A B C"); assert_eq!(Str::uc_words("multiple spaces"), "Multiple Spaces"); assert_eq!(Str::uc_words("123 hello"), "123 Hello"); }
#[cfg(feature = "regex")]
#[test]
fn test_is_username_valid_valid_usernames() {
assert!(Str::is_username_valid("a".to_string()).unwrap());
assert!(Str::is_username_valid("abc1234".to_string()).unwrap());
assert!(Str::is_username_valid("a.b.c".to_string()).unwrap());
assert!(Str::is_username_valid("username1".to_string()).unwrap());
assert!(Str::is_username_valid("a123456789012345678901234567890123".to_string()).unwrap());
}
#[cfg(feature = "regex")]
#[test]
fn test_is_username_valid_invalid_usernames() {
assert!(!Str::is_username_valid("1username".to_string()).unwrap()); assert!(!Str::is_username_valid("username!".to_string()).unwrap()); assert!(!Str::is_username_valid("".to_string()).unwrap()); assert!(
!Str::is_username_valid(
"a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z".to_string()
)
.unwrap()
); }
#[test]
fn test_uuid() {
let uuid = Str::uuid();
assert_eq!(uuid.len(), 32);
assert!(uuid.chars().all(|c| c.is_ascii_hexdigit()));
let uuid_set: std::collections::HashSet<_> = (0..1000).map(|_| Str::uuid()).collect();
assert_eq!(uuid_set.len(), 1000); }
#[test]
fn test_truncate() {
assert_eq!(Str::truncate("Hello, World!", 5), "Hello...");
assert_eq!(Str::truncate("Hello", 10), "Hello");
assert_eq!(Str::truncate("", 5), "");
}
#[test]
fn test_remove_whitespace() {
assert_eq!(Str::remove_whitespace("Hello World"), "HelloWorld");
assert_eq!(Str::remove_whitespace(" spaces "), "spaces");
assert_eq!(Str::remove_whitespace("\t\ntest\r"), "test");
}
#[test]
fn test_reverse() {
assert_eq!(Str::reverse("hello"), "olleh");
assert_eq!(Str::reverse(""), "");
assert_eq!(Str::reverse("Rust"), "tsuR");
}
#[test]
fn test_count_occurrences() {
assert_eq!(Str::count_occurrences("hello hello hello", "hello"), 3);
assert_eq!(Str::count_occurrences("aaa", "aa"), 1);
assert_eq!(Str::count_occurrences("test", ""), 0);
}
#[test]
fn test_is_numeric() {
assert!(Str::is_numeric("123"));
assert!(!Str::is_numeric("12.3"));
assert!(!Str::is_numeric("abc"));
assert!(!Str::is_numeric(""));
}
#[test]
fn test_is_alphabetic() {
assert!(Str::is_alphabetic("abc"));
assert!(Str::is_alphabetic("ABC"));
assert!(!Str::is_alphabetic("abc123"));
assert!(!Str::is_alphabetic(""));
}
#[test]
fn test_to_camel_case() {
assert_eq!(Str::camel_case("hello_world"), "helloWorld");
assert_eq!(Str::camel_case("user_id"), "userId");
assert_eq!(Str::camel_case("already_camelCase"), "alreadyCamelCase");
assert_eq!(Str::camel_case(""), "");
}
#[test]
fn test_pad_left() {
assert_eq!(Str::pad_left("123", 5, '0'), "00123");
assert_eq!(Str::pad_left("abc", 3, '0'), "abc");
assert_eq!(Str::pad_left("", 2, '*'), "**");
}
}
#[cfg(test)]
mod ext_tests {
use crate::ext::StringExt;
#[test]
fn test_uc_first_ext() {
assert_eq!("hello".uc_first(), "Hello");
assert_eq!("hELLO".uc_first(), "HELLO");
assert_eq!("".uc_first(), "");
assert_eq!("1world".uc_first(), "1world");
assert_eq!(String::from("hello").uc_first(), "Hello");
}
#[test]
fn test_uc_words_ext() {
assert_eq!("hello world".uc_words(), "Hello World");
assert_eq!(
"rust programming language".uc_words(),
"Rust Programming Language"
);
assert_eq!("".uc_words(), "");
assert_eq!("a b c".uc_words(), "A B C");
assert_eq!(
String::from("multiple spaces").uc_words(),
"Multiple Spaces"
);
}
#[cfg(feature = "regex")]
#[test]
fn test_is_username_valid_ext() {
assert!("a".is_username_valid().unwrap());
assert!(String::from("abc1234").is_username_valid().unwrap());
assert!(!"".is_username_valid().unwrap());
}
#[test]
fn test_truncate_ext() {
assert_eq!("Hello, World!".truncate(5), "Hello...");
assert_eq!("Hello".truncate(10), "Hello");
assert_eq!("".truncate(5), "");
assert_eq!(String::from("Hello, World!").truncate(5), "Hello...");
}
#[test]
fn test_remove_whitespace_ext() {
assert_eq!("Hello World".remove_whitespace(), "HelloWorld");
assert_eq!(" spaces ".remove_whitespace(), "spaces");
assert_eq!("\t\ntest\r".remove_whitespace(), "test");
assert_eq!(String::from(" a b c ").remove_whitespace(), "abc");
}
#[test]
fn test_reverse_ext() {
assert_eq!("hello".reverse(), "olleh");
assert_eq!("".reverse(), "");
assert_eq!(String::from("Rust").reverse(), "tsuR");
}
#[test]
fn test_count_occurrences_ext() {
assert_eq!("hello hello hello".count_occurrences("hello"), 3);
assert_eq!("aaa".count_occurrences("aa"), 1);
assert_eq!("test".count_occurrences(""), 0);
assert_eq!(String::from("aabbcc").count_occurrences("b"), 2);
}
#[test]
fn test_is_numeric_ext() {
assert!("123".is_numeric());
assert!(!"12.3".is_numeric());
assert!(!"abc".is_numeric());
assert!(!"".is_numeric());
assert!(String::from("456").is_numeric());
}
#[test]
fn test_is_alphabetic_ext() {
assert!("abc".is_alphabetic());
assert!("ABC".is_alphabetic());
assert!(!"abc123".is_alphabetic());
assert!(!"".is_alphabetic());
assert!(String::from("xyzXYZ").is_alphabetic());
}
#[test]
fn test_camel_case_ext() {
assert_eq!("hello_world".camel_case(), "helloWorld");
assert_eq!("user_id".camel_case(), "userId");
assert_eq!("already_camelCase".camel_case(), "alreadyCamelCase");
assert_eq!("".camel_case(), "");
assert_eq!(String::from("foo_bar_baz").camel_case(), "fooBarBaz");
}
#[test]
fn test_pad_left_ext() {
assert_eq!("123".pad_left(5, '0'), "00123");
assert_eq!("abc".pad_left(3, '0'), "abc");
assert_eq!("".pad_left(2, '*'), "**");
assert_eq!(String::from("42").pad_left(4, '-'), "--42");
}
}