rust_store_core/naming/
mod.rs1mod canonical;
4mod conflict;
5
6pub use canonical::{canonical, to_camel, to_pascal, to_snake};
7pub use conflict::{detect_conflicts, ERR_NAME_CONFLICT, RESERVED_KEYS};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum Style {
12 Snake,
14 Camel,
16 Pascal,
18}
19
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
22pub enum Target {
23 Mysql,
25 Postgres,
26 Sqlite,
27 Mongodb,
28 Node,
30 Java,
31 Csharp,
32 Rust,
33 Go,
34 Python,
35}
36
37impl Target {
38 pub fn from_str_or_err(s: &str) -> Result<Target, String> {
40 match s.to_lowercase().as_str() {
41 "mysql" => Ok(Target::Mysql),
42 "postgres" | "pg" | "postgresql" => Ok(Target::Postgres),
43 "sqlite" => Ok(Target::Sqlite),
44 "mongo" | "mongodb" => Ok(Target::Mongodb),
45 "node" | "nodejs" => Ok(Target::Node),
46 "java" => Ok(Target::Java),
47 "csharp" | "cs" | "c#" => Ok(Target::Csharp),
48 "rust" => Ok(Target::Rust),
49 "go" | "golang" => Ok(Target::Go),
50 "python" | "py" => Ok(Target::Python),
51 other => Err(format!("未知命名目标: {other}")),
52 }
53 }
54
55 pub fn for_datasource_kind(kind: &str) -> Result<Target, String> {
57 Target::from_str_or_err(kind)
58 }
59
60 pub fn style(&self) -> Style {
62 match self {
63 Target::Mysql | Target::Postgres | Target::Sqlite | Target::Python => Style::Snake,
64 Target::Mongodb | Target::Node | Target::Java | Target::Csharp | Target::Rust => {
65 Style::Camel
66 }
67 Target::Go => Style::Pascal,
68 }
69 }
70}
71
72pub fn translate(logical: &str, target: Target) -> String {
74 let tokens = canonical(logical);
75 match target.style() {
76 Style::Snake => to_snake(&tokens),
77 Style::Camel => to_camel(&tokens),
78 Style::Pascal => to_pascal(&tokens),
79 }
80}
81
82pub fn translate_by_str(logical: &str, target: &str) -> Result<String, String> {
84 Ok(translate(logical, Target::from_str_or_err(target)?))
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90
91 #[test]
93 fn target_style_table() {
94 assert_eq!(translate("orderTotal", Target::Mysql), "order_total");
95 assert_eq!(translate("orderTotal", Target::Postgres), "order_total");
96 assert_eq!(translate("orderTotal", Target::Sqlite), "order_total");
97 assert_eq!(translate("orderTotal", Target::Mongodb), "orderTotal");
98 assert_eq!(translate("orderTotal", Target::Node), "orderTotal");
99 assert_eq!(translate("orderTotal", Target::Java), "orderTotal");
100 assert_eq!(translate("orderTotal", Target::Csharp), "orderTotal");
101 assert_eq!(translate("orderTotal", Target::Rust), "orderTotal");
102 assert_eq!(translate("orderTotal", Target::Go), "OrderTotal"); assert_eq!(translate("orderTotal", Target::Python), "order_total");
104 }
105
106 #[test]
108 fn design_section_6_2_pipeline() {
109 for src in ["orderTotal", "order_total", "Order.Total"] {
110 assert_eq!(translate(src, Target::Mysql), "order_total");
111 assert_eq!(translate(src, Target::Mongodb), "orderTotal");
112 assert_eq!(translate(src, Target::Go), "OrderTotal");
113 assert_eq!(translate(src, Target::Python), "order_total");
114 }
115 }
116
117 #[test]
118 fn unknown_target_errors() {
119 assert!(Target::from_str_or_err("oracle").is_err());
120 assert!(translate_by_str("orderTotal", "oracle").is_err());
121 }
122}