dampen_core/codegen/
config.rs1use std::path::PathBuf;
7
8#[derive(Debug, Clone)]
10pub struct CodegenConfig {
11 pub output_dir: PathBuf,
13
14 pub format_output: bool,
16
17 pub validate_syntax: bool,
19
20 pub model_type: String,
22
23 pub message_type: String,
25}
26
27impl CodegenConfig {
28 pub fn new(output_dir: PathBuf) -> Self {
36 Self {
37 output_dir,
38 format_output: true,
39 validate_syntax: true,
40 model_type: "Model".to_string(),
41 message_type: "Message".to_string(),
42 }
43 }
44
45 pub fn with_model_type(mut self, model_type: impl Into<String>) -> Self {
47 self.model_type = model_type.into();
48 self
49 }
50
51 pub fn with_message_type(mut self, message_type: impl Into<String>) -> Self {
53 self.message_type = message_type.into();
54 self
55 }
56
57 pub fn with_formatting(mut self, format_output: bool) -> Self {
59 self.format_output = format_output;
60 self
61 }
62
63 pub fn with_validation(mut self, validate_syntax: bool) -> Self {
65 self.validate_syntax = validate_syntax;
66 self
67 }
68
69 pub fn validate(&self) -> Result<(), String> {
74 if self.output_dir.as_os_str().is_empty() {
76 return Err("Output directory cannot be empty".to_string());
77 }
78
79 if !is_valid_identifier(&self.model_type) {
81 return Err(format!(
82 "Model type '{}' is not a valid Rust identifier",
83 self.model_type
84 ));
85 }
86
87 if !is_valid_identifier(&self.message_type) {
89 return Err(format!(
90 "Message type '{}' is not a valid Rust identifier",
91 self.message_type
92 ));
93 }
94
95 Ok(())
96 }
97}
98
99impl Default for CodegenConfig {
100 fn default() -> Self {
101 Self::new(PathBuf::from("target/generated"))
102 }
103}
104
105fn is_valid_identifier(s: &str) -> bool {
111 if s.is_empty() {
112 return false;
113 }
114
115 let mut chars = s.chars();
116
117 if let Some(first) = chars.next() {
119 if !first.is_uppercase() {
120 return false;
121 }
122 } else {
123 return false;
124 }
125
126 chars.all(|c| c.is_alphanumeric() || c == '_')
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn test_valid_identifiers() {
136 assert!(is_valid_identifier("Model"));
137 assert!(is_valid_identifier("MyModel"));
138 assert!(is_valid_identifier("Model123"));
139 assert!(is_valid_identifier("My_Model"));
140 assert!(is_valid_identifier("M"));
141 }
142
143 #[test]
144 fn test_invalid_identifiers() {
145 assert!(!is_valid_identifier(""));
146 assert!(!is_valid_identifier("model")); assert!(!is_valid_identifier("123Model")); assert!(!is_valid_identifier("My-Model")); assert!(!is_valid_identifier("My Model")); assert!(!is_valid_identifier("_Model")); }
152
153 #[test]
154 fn test_config_validation() {
155 let config = CodegenConfig::default();
156 assert!(config.validate().is_ok());
157
158 let config = CodegenConfig::new(PathBuf::from("")).with_model_type("Model");
159 assert!(config.validate().is_err());
160
161 let config = CodegenConfig::new(PathBuf::from("target")).with_model_type("invalid");
162 assert!(config.validate().is_err());
163
164 let config = CodegenConfig::new(PathBuf::from("target")).with_message_type("invalid");
165 assert!(config.validate().is_err());
166 }
167}