#[must_use]
pub fn rust_to_pascal(name: &str) -> String {
let mut result = String::with_capacity(name.len());
let mut capitalize_next = true;
for c in name.chars() {
if c == '_' || c == ' ' {
capitalize_next = true;
} else if capitalize_next {
result.extend(c.to_uppercase());
capitalize_next = false;
} else {
result.push(c);
}
}
result
}
#[must_use]
pub fn sanitize_rust_name(name: &str) -> String {
let mut result = String::with_capacity(name.len());
let mut capitalize_next = true;
for c in name.chars() {
match c {
'<' | '>' | ',' | ';' | '[' | ']' | ' ' | '\'' => {
capitalize_next = true;
}
'_' => {
capitalize_next = true;
}
_ if capitalize_next => {
result.extend(c.to_uppercase());
capitalize_next = false;
}
_ => {
result.push(c);
}
}
}
result
}
#[must_use]
pub fn pascal_to_snake(name: &str) -> String {
let mut result = String::with_capacity(name.len() + 4);
for (i, c) in name.chars().enumerate() {
if c.is_uppercase() && i > 0 {
let prev = name.as_bytes()[i - 1];
if prev.is_ascii_lowercase() || prev.is_ascii_digit() {
result.push('_');
}
}
result.extend(c.to_lowercase());
}
result
}
#[must_use]
pub fn service_method_name(type_name: &str, fn_name: &str) -> String {
let prefix = pascal_to_snake(type_name);
let method_part = fn_name.strip_prefix(&prefix).and_then(|s| s.strip_prefix('_')).unwrap_or(fn_name);
rust_to_pascal(method_part)
}
#[must_use]
pub fn sanitize_delegate_name(name: &str) -> String {
let stripped = name.strip_prefix("extern \"C\" ").unwrap_or(name);
let stripped = stripped.replace("-> ()", "");
let mut result = String::with_capacity(stripped.len());
let mut capitalize_next = true;
for c in stripped.chars() {
if c.is_alphanumeric() {
if capitalize_next {
result.extend(c.to_uppercase());
capitalize_next = false;
} else {
result.push(c);
}
} else {
capitalize_next = true;
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_pascal_to_snake() {
assert_eq!(pascal_to_snake("ServiceBasic"), "service_basic");
assert_eq!(pascal_to_snake("Vec3"), "vec3");
assert_eq!(pascal_to_snake("MyType"), "my_type");
assert_eq!(pascal_to_snake("A"), "a");
assert_eq!(pascal_to_snake(""), "");
assert_eq!(pascal_to_snake("already_snake"), "already_snake");
}
#[test]
fn test_rust_to_pascal() {
assert_eq!(rust_to_pascal("my_type"), "MyType");
assert_eq!(rust_to_pascal("vec3_f32"), "Vec3F32");
assert_eq!(rust_to_pascal("already"), "Already");
assert_eq!(rust_to_pascal("a_b_c"), "ABC");
}
#[test]
fn test_service_method_name() {
assert_eq!(service_method_name("ServiceBasic", "service_basic_do_something"), "DoSomething");
assert_eq!(service_method_name("ServiceBasic", "unrelated_name"), "UnrelatedName");
assert_eq!(service_method_name("MyService", "my_service_new"), "New");
}
#[test]
fn test_sanitize_rust_name() {
assert_eq!(sanitize_rust_name("Weird2<u8, 5>"), "Weird2U85");
assert_eq!(sanitize_rust_name("[u8; 5]"), "U85");
assert_eq!(sanitize_rust_name("MyStruct"), "MyStruct");
assert_eq!(sanitize_rust_name("Generic<'_, u32>"), "GenericU32");
assert_eq!(sanitize_rust_name("Weird2<'_, u8, 5>"), "Weird2U85");
assert_eq!(sanitize_rust_name("Phantom<'_, u8>"), "PhantomU8");
}
#[test]
fn test_sanitize_delegate_name() {
assert_eq!(sanitize_delegate_name("extern \"C\" fn(u8) -> u8"), "FnU8U8");
assert_eq!(sanitize_delegate_name("extern \"C\" fn(Vec3f32) -> ()"), "FnVec3f32");
assert_eq!(sanitize_delegate_name("fn(u32, u32) -> bool"), "FnU32U32Bool");
}
}