pub fn to_rust_type_name(name: &str) -> String {
let chars: Vec<char> = name.chars().collect();
if chars.is_empty() {
return String::new();
}
let mut result = String::with_capacity(name.len());
let mut i = 0;
while i < chars.len() {
if chars[i].is_ascii_uppercase() {
let start = i;
while i < chars.len() && chars[i].is_ascii_uppercase() {
i += 1;
}
let upper_run = i - start;
if upper_run == 1 {
result.push(chars[start]);
} else if i < chars.len() && chars[i].is_ascii_lowercase() {
result.push(chars[start]);
for c in chars.iter().take(i - 1).skip(start + 1) {
result.push(c.to_ascii_lowercase());
}
result.push(chars[i - 1]);
} else {
result.push(chars[start]);
for c in chars.iter().take(i).skip(start + 1) {
result.push(c.to_ascii_lowercase());
}
}
} else {
result.push(chars[i]);
i += 1;
}
}
result
}
pub fn to_rust_field_name(name: &str) -> String {
name.to_string()
}
pub fn to_rust_variant_name(name: &str) -> String {
let mut chars = name.chars();
match chars.next() {
Some(c) => {
let mut result = c.to_uppercase().to_string();
result.extend(chars);
result
}
None => String::new(),
}
}
pub fn to_builder_name(type_name: &str) -> String {
format!("{}Builder", to_rust_type_name(type_name))
}
pub fn to_union_enum_name(type_name: &str, field_name: &str) -> String {
format!(
"{}{}Value",
to_rust_type_name(type_name),
to_rust_variant_name(field_name)
)
}
pub fn imported_module_prefix(from_ns: &str, to_ns: &str) -> String {
let from: Vec<&str> = from_ns.split('/').collect();
let to: Vec<&str> = to_ns.split('/').collect();
let common = from
.iter()
.zip(to.iter())
.take_while(|(a, b)| a == b)
.count();
let mut path = String::new();
for _ in 0..(from.len() - common) {
path.push_str("super::");
}
for segment in &to[common..] {
path.push_str(segment);
path.push_str("::");
}
path
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn type_name_simple() {
assert_eq!(to_rust_type_name("Record"), "Record");
}
#[test]
fn type_name_all_caps_prefix() {
assert_eq!(to_rust_type_name("CSVLine"), "CsvLine");
assert_eq!(to_rust_type_name("CSVFieldValue"), "CsvFieldValue");
assert_eq!(to_rust_type_name("CSVFieldValues"), "CsvFieldValues");
assert_eq!(to_rust_type_name("CSVFile"), "CsvFile");
assert_eq!(to_rust_type_name("CSVLines"), "CsvLines");
}
#[test]
fn type_name_all_caps() {
assert_eq!(to_rust_type_name("CSV"), "Csv");
assert_eq!(to_rust_type_name("IO"), "Io");
}
#[test]
fn type_name_already_pascal() {
assert_eq!(to_rust_type_name("ScalarValue"), "ScalarValue");
assert_eq!(to_rust_type_name("Node"), "Node");
}
#[test]
fn variant_name() {
assert_eq!(to_rust_variant_name("public"), "Public");
assert_eq!(to_rust_variant_name("protected"), "Protected");
assert_eq!(to_rust_variant_name("Red"), "Red");
}
#[test]
fn builder_name() {
assert_eq!(to_builder_name("CSVLine"), "CsvLineBuilder");
assert_eq!(to_builder_name("Record"), "RecordBuilder");
}
#[test]
fn union_enum_name() {
assert_eq!(
to_union_enum_name("CSVFieldValue", "value"),
"CsvFieldValueValueValue"
);
}
}