use std::str::Chars;
use unidecode::unidecode_char;
#[inline]
fn transliterate(c: char) -> Chars<'static> {
let s = unidecode_char(c);
if s.is_empty() {};
unidecode_char(c).chars()
}
#[inline]
fn ascii_to_lower_if_alpha(c: char) -> Option<char> {
debug_assert!(c.is_ascii(), "{}", c.to_string());
if c.is_ascii_lowercase() {
Some(c)
} else if c.is_ascii_uppercase() {
Some(c.to_ascii_lowercase())
} else {
None
}
}
#[inline]
fn ascii_to_upper_if_alpha(c: char) -> Option<char> {
debug_assert!(c.is_ascii(), "{}", c.to_string());
if c.is_ascii_uppercase() {
Some(c)
} else if c.is_ascii_lowercase() {
Some(c.to_ascii_uppercase())
} else {
None
}
}
#[inline]
pub fn to_ascii_initial(c: char) -> Option<char> {
match c {
'A'..='Z' => Some(c),
_ => transliterate(c).find_map(ascii_to_upper_if_alpha),
}
}
pub fn to_ascii_casefolded(text: &str) -> Option<impl Iterator<Item = char> + '_> {
let mut result = text
.chars()
.flat_map(transliterate)
.filter_map(ascii_to_lower_if_alpha)
.peekable();
let has_next = result.peek().is_some();
if has_next {
Some(result)
} else {
None
}
}
pub fn to_ascii_casefolded_reversed(text: &str) -> Option<impl Iterator<Item = char> + '_> {
let mut result = text
.chars()
.flat_map(transliterate)
.rev()
.filter_map(ascii_to_lower_if_alpha)
.peekable();
let has_next = result.peek().is_some();
if has_next {
Some(result)
} else {
None
}
}
pub fn to_ascii_titlecase(s: &str) -> Option<String> {
let mut result = s
.chars()
.flat_map(transliterate)
.filter_map(ascii_to_lower_if_alpha);
result.next().map(|initial| {
let mut s = String::with_capacity(s.len());
s.push(initial);
s.extend(result);
s
})
}