pub fn generate_reverse_accessor(model_name: &str) -> String {
let snake_case = to_snake_case(model_name);
format!("{}_set", snake_case)
}
pub fn generate_reverse_accessor_singular(model_name: &str) -> String {
to_snake_case(model_name)
}
pub fn to_snake_case(s: &str) -> String {
let mut result = String::new();
let chars: Vec<char> = s.chars().collect();
for (i, &ch) in chars.iter().enumerate() {
if ch.is_uppercase() {
if i > 0 {
let prev_is_lower = chars[i - 1].is_lowercase();
let next_is_lower = i + 1 < chars.len() && chars[i + 1].is_lowercase();
if prev_is_lower || next_is_lower {
result.push('_');
}
}
result.push(ch.to_ascii_lowercase());
} else {
result.push(ch);
}
}
result
}
pub trait ReverseRelationship {
fn get_or_generate_reverse_name(&self, model_name: &str) -> String;
fn explicit_reverse_name(&self) -> Option<&str>;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generate_reverse_accessor() {
assert_eq!(generate_reverse_accessor("Post"), "post_set");
assert_eq!(generate_reverse_accessor("Comment"), "comment_set");
assert_eq!(generate_reverse_accessor("UserProfile"), "user_profile_set");
assert_eq!(generate_reverse_accessor("BlogPost"), "blog_post_set");
}
#[test]
fn test_generate_reverse_accessor_singular() {
assert_eq!(
generate_reverse_accessor_singular("UserProfile"),
"user_profile"
);
assert_eq!(generate_reverse_accessor_singular("Address"), "address");
assert_eq!(generate_reverse_accessor_singular("Profile"), "profile");
}
#[test]
fn test_to_snake_case() {
assert_eq!(to_snake_case("UserProfile"), "user_profile");
assert_eq!(to_snake_case("Post"), "post");
assert_eq!(to_snake_case("BlogPost"), "blog_post");
assert_eq!(to_snake_case("APIKey"), "api_key");
assert_eq!(to_snake_case("HTTPRequest"), "http_request");
}
#[test]
fn test_to_snake_case_single_char() {
assert_eq!(to_snake_case("A"), "a");
assert_eq!(to_snake_case("B"), "b");
}
#[test]
fn test_to_snake_case_already_lowercase() {
assert_eq!(to_snake_case("post"), "post");
assert_eq!(to_snake_case("user"), "user");
}
#[test]
fn test_to_snake_case_mixed() {
assert_eq!(to_snake_case("XMLHttpRequest"), "xml_http_request");
assert_eq!(to_snake_case("IOError"), "io_error");
}
#[test]
fn test_to_snake_case_consecutive_uppercase() {
assert_eq!(to_snake_case("HTTPSConnection"), "https_connection");
assert_eq!(to_snake_case("URLPattern"), "url_pattern");
}
}