use alloc::string::{String, ToString};
use alloc::vec::Vec;
fn lowercase_word(word: &str) -> String {
word.to_lowercase()
}
fn uppercase_word(word: &str) -> String {
word.to_uppercase()
}
fn capital_word(word: &str) -> String {
let mut chars = word.chars();
if let Some(c) = chars.next() {
[c.to_uppercase().collect(), chars.as_str().to_lowercase()].concat()
} else {
String::new()
}
}
#[derive(Debug, Copy, Clone)]
pub enum Pattern {
Lowercase,
Uppercase,
Capital,
Camel,
Sentence,
RemoveEmpty,
Custom(fn(&[&str]) -> Vec<String>),
}
impl Pattern {
pub fn mutate<S: AsRef<str>>(&self, words: &[S]) -> Vec<String> {
use Pattern::*;
match self {
Custom(transformation) => {
let borrowed: Vec<&str> = words.iter().map(|s| s.as_ref()).collect();
(transformation)(&borrowed)
}
Lowercase => words
.iter()
.map(|word| lowercase_word(word.as_ref()))
.collect(),
Uppercase => words
.iter()
.map(|word| uppercase_word(word.as_ref()))
.collect(),
Capital => words
.iter()
.map(|word| capital_word(word.as_ref()))
.collect(),
Camel => words
.iter()
.enumerate()
.map(|(i, word)| {
if i == 0 {
lowercase_word(word.as_ref())
} else {
capital_word(word.as_ref())
}
})
.collect(),
Sentence => words
.iter()
.enumerate()
.map(|(i, word)| {
if i == 0 {
capital_word(word.as_ref())
} else {
lowercase_word(word.as_ref())
}
})
.collect(),
RemoveEmpty => words
.iter()
.filter(|word| !word.as_ref().is_empty())
.map(|word| word.as_ref().to_string())
.collect(),
}
}
}
impl PartialEq for Pattern {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Lowercase, Self::Lowercase) => true,
(Self::Uppercase, Self::Uppercase) => true,
(Self::Capital, Self::Capital) => true,
(Self::Camel, Self::Camel) => true,
(Self::Sentence, Self::Sentence) => true,
(Self::RemoveEmpty, Self::RemoveEmpty) => true,
(Self::Custom(_), Self::Custom(_)) => false,
_ => false,
}
}
}
impl Eq for Pattern {}
impl core::hash::Hash for Pattern {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
core::mem::discriminant(self).hash(state);
}
}
#[cfg(test)]
mod test {
use crate::Case;
use crate::Converter;
use super::*;
#[test]
fn mutate_empty_strings() {
for word_pattern in [lowercase_word, uppercase_word, capital_word] {
assert_eq!(String::new(), word_pattern(&String::new()))
}
}
#[test]
fn filtering_with_remove_empty() {
let conv = Converter::new()
.from_case(Case::Kebab)
.set_patterns(&[Pattern::RemoveEmpty, Pattern::Camel]);
assert_eq!(conv.convert("--leading-delims"), "leadingDelims");
}
#[test]
fn remove_empty_pattern() {
assert_eq!(
Pattern::RemoveEmpty.mutate(&["", "first", "", "second", ""]),
vec!["first", "second"]
);
assert_eq!(Pattern::RemoveEmpty.mutate(&["only"]), vec!["only"]);
assert_eq!(
Pattern::RemoveEmpty.mutate(&["", "", ""]),
Vec::<String>::new()
);
}
}