pub(super) fn tit_cap(name: &str) -> String {
if name.len() <= 1 {
return name.into();
}
let is_high = |c: char| c.is_ascii_uppercase() | c.is_ascii_digit();
let mut res = String::new();
let mut ch = name.chars();
let mut prev = ch.next().unwrap();
res.push(prev.to_ascii_uppercase());
let mut c = ch.next().unwrap();
for next in ch {
if c != '_' {
if is_high(c) && is_high(prev) && (is_high(next) || next == '_') {
res.push(c.to_ascii_lowercase())
} else if prev == '_' && c != '_' {
res.push(c.to_ascii_uppercase())
} else {
res.push(c)
}
}
prev = c;
c = next;
}
if is_high(c) && is_high(prev) {
res.push(c.to_ascii_lowercase());
} else {
res.push(c);
}
res
}
#[test]
fn test_tit_cap() {
assert!(tit_cap("SomeString") == "SomeString");
assert!(tit_cap("WINDOW") == "Window");
assert!(tit_cap("CONTEXT_TAG") == "ContextTag");
assert!(tit_cap("value_list") == "ValueList");
assert!(tit_cap("GContext") == "GContext");
assert!(tit_cap("IDChoice") == "IdChoice");
}
pub(super) fn tit_split(name: &str) -> String {
if name.len() <= 1 {
return name.into();
}
let is_high = |c: char| c.is_ascii_uppercase();
let is_low = |c: char| c.is_ascii_lowercase();
let mut res = String::new();
let mut ch = name.chars();
let mut prev = ch.next().unwrap();
res.push(prev);
let mut c = ch.next().unwrap();
for next in ch {
if (is_low(prev) && is_high(c) || is_high(c) && is_low(next)) && prev != '_' {
res.push('_');
}
res.push(c);
prev = c;
c = next;
}
if is_low(prev) && is_high(c) && prev != '_' {
res.push('_');
}
res.push(c);
res
}
#[test]
fn test_tit_split() {
assert_eq!(tit_dig("SomeString"), "Some_String");
assert_eq!(tit_dig("WINDOW"), "WINDOW");
}
pub(super) fn to_snake_case(name: &str) -> String {
tit_split(name).to_ascii_lowercase()
}
pub(super) fn extract_module(typ: &str) -> (Option<&str>, &str) {
let len = typ.len();
let colon = typ.as_bytes().iter().position(|b| *b == b':');
if let Some(colon) = colon {
(Some(&typ[0..colon]), &typ[colon + 1..len])
} else {
(None, typ)
}
}