pub fn to_snake_case(name: &str) -> String {
if name.is_empty() {
return String::new();
}
let mut result = String::with_capacity(name.len() + 4);
let chars: Vec<char> = name.chars().collect();
let mut prev_was_separator = true;
for i in 0..chars.len() {
let ch = chars[i];
if ch == '_' || ch == '-' || ch == ' ' || ch == '.' {
if !prev_was_separator && !result.is_empty() {
result.push('_');
}
prev_was_separator = true;
} else if ch.is_ascii_uppercase() {
if !prev_was_separator && i > 0 {
let prev = chars[i - 1];
let next = chars.get(i + 1);
if prev.is_ascii_lowercase()
|| (prev.is_ascii_uppercase() && next.is_some_and(|&n| n.is_ascii_lowercase()))
{
result.push('_');
}
}
result.push(ch.to_ascii_lowercase());
prev_was_separator = false;
} else {
result.push(ch.to_ascii_lowercase());
prev_was_separator = false;
}
}
result
}