Skip to main content

gize_core/
naming.rs

1//! Naming conventions shared across generators.
2//!
3//! Centralised so every crate agrees on how a model name maps to a module name, a table
4//! name, etc. Kept dependency-free (no heavy inflection crate) for the MVP.
5
6/// Convert a `PascalCase` or arbitrary identifier to `snake_case`.
7pub fn snake_case(input: &str) -> String {
8    let mut out = String::with_capacity(input.len() + 4);
9    for (i, ch) in input.chars().enumerate() {
10        if ch.is_uppercase() {
11            if i != 0 {
12                out.push('_');
13            }
14            for lower in ch.to_lowercase() {
15                out.push(lower);
16            }
17        } else {
18            out.push(ch);
19        }
20    }
21    out
22}
23
24/// Naive pluralisation good enough for table names in the MVP.
25pub fn pluralize(word: &str) -> String {
26    if word.ends_with('y')
27        && !word.ends_with("ay")
28        && !word.ends_with("ey")
29        && !word.ends_with("oy")
30        && !word.ends_with("uy")
31    {
32        format!("{}ies", &word[..word.len() - 1])
33    } else if word.ends_with('s')
34        || word.ends_with("x")
35        || word.ends_with("ch")
36        || word.ends_with("sh")
37    {
38        format!("{word}es")
39    } else {
40        format!("{word}s")
41    }
42}
43
44/// The table name for a model (snake_case + pluralized): `User` -> `users`.
45pub fn table_name(model: &str) -> String {
46    pluralize(&snake_case(model))
47}
48
49#[cfg(test)]
50mod tests {
51    use super::*;
52
53    #[test]
54    fn snake_cases() {
55        assert_eq!(snake_case("User"), "user");
56        assert_eq!(snake_case("BlogPost"), "blog_post");
57        assert_eq!(snake_case("OAuthToken"), "o_auth_token");
58    }
59
60    #[test]
61    fn pluralizes() {
62        assert_eq!(pluralize("user"), "users");
63        assert_eq!(pluralize("category"), "categories");
64        assert_eq!(pluralize("box"), "boxes");
65        assert_eq!(pluralize("day"), "days");
66    }
67
68    #[test]
69    fn builds_table_names() {
70        assert_eq!(table_name("User"), "users");
71        assert_eq!(table_name("BlogPost"), "blog_posts");
72        assert_eq!(table_name("Category"), "categories");
73    }
74}