1use crate::error::{Error, Result};
7use std::sync::{Arc, Mutex, OnceLock};
8
9use super::{
10 antlr_backend::AntlrParser,
11 config::{ParserBackend, ParserConfig},
12 nom_backend::NomParser,
13 traits::{CqlParser, CqlParserFactory, FactoryInfo, ParserBackendInfo},
14};
15
16#[derive(Debug, Default)]
18pub struct ParserFactory;
19
20impl ParserFactory {
21 pub fn create_default() -> Result<Arc<dyn CqlParser + Send + Sync>> {
23 Self::create(ParserConfig::default())
24 }
25
26 pub fn create(mut config: ParserConfig) -> Result<Arc<dyn CqlParser + Send + Sync>> {
28 config.validate().map_err(Error::configuration)?;
29
30 if matches!(config.backend, ParserBackend::Auto) {
31 config.backend = Self::select_optimal_backend(&config);
32 }
33
34 match config.backend.clone() {
35 ParserBackend::Nom => Ok(Arc::new(NomParser::new(config)?)),
36 ParserBackend::Antlr => Ok(Arc::new(AntlrParser::new(config)?)),
37 ParserBackend::Auto => unreachable!("Auto resolved above"),
38 ParserBackend::Custom(name) => Err(Error::configuration(format!(
39 "Custom parser '{}' not available",
40 name
41 ))),
42 }
43 }
44
45 fn select_optimal_backend(config: &ParserConfig) -> ParserBackend {
50 use super::config::ParserFeature;
51
52 let needs_antlr = config.has_feature(&ParserFeature::ErrorRecovery)
53 || config.has_feature(&ParserFeature::SyntaxHighlighting)
54 || config.has_feature(&ParserFeature::CodeCompletion)
55 || config.strict_validation;
56
57 if needs_antlr {
58 ParserBackend::Antlr
59 } else {
60 ParserBackend::Nom
61 }
62 }
63
64 pub fn get_available_backends() -> Vec<ParserBackendInfo> {
66 vec![NomParser::backend_info(), AntlrParser::backend_info()]
67 }
68
69 pub fn is_backend_available(backend: &ParserBackend) -> bool {
71 match backend {
72 ParserBackend::Nom | ParserBackend::Antlr | ParserBackend::Auto => true,
73 ParserBackend::Custom(_) => false,
74 }
75 }
76
77 pub fn recommend_backend(use_case: UseCase) -> ParserBackend {
79 match use_case {
80 UseCase::HighPerformance | UseCase::Embedded | UseCase::Batch => ParserBackend::Nom,
81 UseCase::Development | UseCase::Interactive => ParserBackend::Antlr,
82 UseCase::Production => ParserBackend::Auto,
83 }
84 }
85
86 pub fn create_for_use_case(use_case: UseCase) -> Result<Arc<dyn CqlParser + Send + Sync>> {
88 let backend = Self::recommend_backend(use_case.clone());
89 Self::create(Self::create_config_for_use_case(use_case, backend))
90 }
91
92 fn create_config_for_use_case(use_case: UseCase, backend: ParserBackend) -> ParserConfig {
93 use super::config::ParserFeature;
94 use std::time::Duration;
95
96 match use_case {
97 UseCase::HighPerformance => ParserConfig::fast().with_backend(backend),
98 UseCase::Development => ParserConfig::development().with_backend(backend),
99 UseCase::Production => ParserConfig::default().with_backend(backend),
100 UseCase::Embedded => ParserConfig::minimal().with_backend(backend),
101 UseCase::Interactive => ParserConfig::development()
102 .with_backend(backend)
103 .with_feature(ParserFeature::CodeCompletion)
104 .with_feature(ParserFeature::SyntaxHighlighting)
105 .with_timeout(Duration::from_millis(100)),
106 UseCase::Batch => ParserConfig::fast()
107 .with_backend(backend)
108 .with_feature(ParserFeature::Parallel)
109 .with_timeout(Duration::from_secs(300)),
110 }
111 }
112}
113
114impl CqlParserFactory for ParserFactory {
115 fn create_parser(&self) -> Result<Box<dyn CqlParser>> {
116 self.create_parser_with_config(ParserConfig::default())
117 }
118
119 fn create_parser_with_config(&self, config: ParserConfig) -> Result<Box<dyn CqlParser>> {
120 Ok(Box::new(ParserWrapper {
121 inner: Self::create(config)?,
122 }))
123 }
124
125 fn factory_info(&self) -> FactoryInfo {
126 FactoryInfo {
127 name: "DefaultParserFactory".to_string(),
128 supported_backends: vec!["nom".to_string(), "antlr".to_string()],
129 default_backend: "auto".to_string(),
130 }
131 }
132}
133
134#[derive(Debug)]
138struct ParserWrapper {
139 inner: Arc<dyn CqlParser + Send + Sync>,
140}
141
142#[async_trait::async_trait]
143impl CqlParser for ParserWrapper {
144 async fn parse(&self, input: &str) -> Result<super::ast::CqlStatement> {
145 self.inner.parse(input).await
146 }
147
148 async fn parse_type(&self, input: &str) -> Result<super::ast::CqlDataType> {
149 self.inner.parse_type(input).await
150 }
151
152 async fn parse_expression(&self, input: &str) -> Result<super::ast::CqlExpression> {
153 self.inner.parse_expression(input).await
154 }
155
156 async fn parse_identifier(&self, input: &str) -> Result<super::ast::CqlIdentifier> {
157 self.inner.parse_identifier(input).await
158 }
159
160 async fn parse_literal(&self, input: &str) -> Result<super::ast::CqlLiteral> {
161 self.inner.parse_literal(input).await
162 }
163
164 async fn parse_column_definitions(&self, input: &str) -> Result<Vec<super::ast::CqlColumnDef>> {
165 self.inner.parse_column_definitions(input).await
166 }
167
168 async fn parse_table_options(&self, input: &str) -> Result<super::ast::CqlTableOptions> {
169 self.inner.parse_table_options(input).await
170 }
171
172 fn validate_syntax(&self, input: &str) -> bool {
173 self.inner.validate_syntax(input)
174 }
175
176 fn backend_info(&self) -> super::traits::ParserBackendInfo {
177 self.inner.backend_info()
178 }
179}
180
181#[derive(Debug, Clone, PartialEq)]
183pub enum UseCase {
184 HighPerformance,
186 Development,
188 Production,
190 Embedded,
192 Interactive,
194 Batch,
196}
197
198#[derive(Debug, Default)]
200pub struct ParserRegistry {
201 custom_factories: std::collections::HashMap<String, Box<dyn CqlParserFactory + Send + Sync>>,
202}
203
204impl ParserRegistry {
205 pub fn new() -> Self {
206 Self::default()
207 }
208
209 pub fn register_factory(
210 &mut self,
211 name: String,
212 factory: Box<dyn CqlParserFactory + Send + Sync>,
213 ) {
214 self.custom_factories.insert(name, factory);
215 }
216
217 pub fn get_factory(&self, name: &str) -> Option<&(dyn CqlParserFactory + Send + Sync)> {
218 self.custom_factories.get(name).map(|f| f.as_ref())
219 }
220
221 pub fn list_factories(&self) -> Vec<&str> {
222 self.custom_factories.keys().map(|s| s.as_str()).collect()
223 }
224
225 pub fn create_with_factory(
227 &self,
228 factory_name: &str,
229 config: ParserConfig,
230 ) -> Result<Box<dyn CqlParser>> {
231 self.get_factory(factory_name)
232 .ok_or_else(|| Error::configuration(format!("Factory '{}' not found", factory_name)))?
233 .create_parser_with_config(config)
234 }
235}
236
237static GLOBAL_REGISTRY: OnceLock<Mutex<ParserRegistry>> = OnceLock::new();
238
239pub fn register_global_factory(name: String, factory: Box<dyn CqlParserFactory + Send + Sync>) {
241 let registry = GLOBAL_REGISTRY.get_or_init(|| Mutex::new(ParserRegistry::new()));
242 let mut guard = registry.lock().unwrap_or_else(|e| e.into_inner());
243 guard.register_factory(name, factory);
244}
245
246pub mod benchmarks {
248 use super::*;
249 use std::time::{Duration, Instant};
250
251 #[derive(Debug, Clone)]
252 pub struct BenchmarkResult {
253 pub backend: String,
254 pub avg_parse_time: Duration,
255 pub min_parse_time: Duration,
256 pub max_parse_time: Duration,
257 pub success_rate: f64,
258 pub errors: Vec<String>,
259 }
260
261 impl BenchmarkResult {
262 fn failed(backend: &ParserBackend, error: String) -> Self {
263 Self {
264 backend: format!("{:?}", backend),
265 avg_parse_time: Duration::ZERO,
266 min_parse_time: Duration::ZERO,
267 max_parse_time: Duration::ZERO,
268 success_rate: 0.0,
269 errors: vec![error],
270 }
271 }
272 }
273
274 #[derive(Debug, Clone)]
275 pub struct BenchmarkConfig {
276 pub iterations: u32,
277 pub timeout: Duration,
278 pub test_cases: Vec<String>,
279 }
280
281 impl Default for BenchmarkConfig {
282 fn default() -> Self {
283 Self {
284 iterations: 100,
285 timeout: Duration::from_secs(1),
286 test_cases: vec![
287 "SELECT * FROM users".to_string(),
288 "INSERT INTO users (id, name) VALUES (?, ?)".to_string(),
289 "UPDATE users SET name = ? WHERE id = ?".to_string(),
290 "DELETE FROM users WHERE id = ?".to_string(),
291 "CREATE TABLE test (id UUID PRIMARY KEY, data TEXT)".to_string(),
292 ],
293 }
294 }
295 }
296
297 pub async fn benchmark_parsers(config: BenchmarkConfig) -> Vec<BenchmarkResult> {
299 let mut results = Vec::new();
300 for backend in [ParserBackend::Nom, ParserBackend::Antlr] {
301 if ParserFactory::is_backend_available(&backend) {
302 results.push(benchmark_backend(backend, &config).await);
303 }
304 }
305 results
306 }
307
308 async fn benchmark_backend(
309 backend: ParserBackend,
310 config: &BenchmarkConfig,
311 ) -> BenchmarkResult {
312 let parser_config = ParserConfig::default().with_backend(backend.clone());
313 let parser = match ParserFactory::create(parser_config) {
314 Ok(p) => p,
315 Err(e) => {
316 return BenchmarkResult::failed(&backend, format!("Failed to create parser: {}", e))
317 }
318 };
319
320 let mut times = Vec::new();
321 let mut errors = Vec::new();
322 let mut successes: u32 = 0;
323
324 for _ in 0..config.iterations {
325 for test_case in &config.test_cases {
326 let start = Instant::now();
327 match tokio::time::timeout(config.timeout, parser.parse(test_case)).await {
328 Ok(Ok(_)) => {
329 successes += 1;
330 times.push(start.elapsed());
331 }
332 Ok(Err(e)) => errors.push(format!("Parse error: {}", e)),
333 Err(_) => errors.push("Timeout".to_string()),
334 }
335 }
336 }
337
338 let total_attempts = config.iterations * config.test_cases.len() as u32;
339 let success_rate = f64::from(successes) / f64::from(total_attempts);
340 let avg_parse_time = if times.is_empty() {
341 Duration::ZERO
342 } else {
343 times.iter().sum::<Duration>() / times.len() as u32
344 };
345
346 BenchmarkResult {
347 backend: format!("{:?}", backend),
348 avg_parse_time,
349 min_parse_time: times.iter().min().copied().unwrap_or_default(),
350 max_parse_time: times.iter().max().copied().unwrap_or_default(),
351 success_rate,
352 errors,
353 }
354 }
355}
356
357#[cfg(test)]
358mod tests {
359 use super::*;
360
361 #[test]
362 fn test_factory_creation() {
363 let factory = ParserFactory;
364 let info = factory.factory_info();
365 assert_eq!(info.name, "DefaultParserFactory");
366 assert!(!info.supported_backends.is_empty());
367 }
368
369 #[test]
370 fn test_backend_availability() {
371 assert!(ParserFactory::is_backend_available(&ParserBackend::Nom));
372 assert!(ParserFactory::is_backend_available(&ParserBackend::Auto));
373 assert!(!ParserFactory::is_backend_available(
374 &ParserBackend::Custom("unknown".to_string())
375 ));
376 }
377
378 #[test]
379 fn test_backend_recommendation() {
380 assert_eq!(
381 ParserFactory::recommend_backend(UseCase::HighPerformance),
382 ParserBackend::Nom
383 );
384 assert_eq!(
385 ParserFactory::recommend_backend(UseCase::Development),
386 ParserBackend::Antlr
387 );
388 }
389
390 #[test]
391 fn test_auto_backend_selection() {
392 let config = ParserConfig::fast();
393 let backend = ParserFactory::select_optimal_backend(&config);
394 assert_eq!(backend, ParserBackend::Nom);
395
396 let config = ParserConfig::strict();
397 let backend = ParserFactory::select_optimal_backend(&config);
398 assert_eq!(backend, ParserBackend::Antlr);
399 }
400
401 #[test]
402 fn test_parser_registry() {
403 let registry = ParserRegistry::new();
404 assert!(registry.list_factories().is_empty());
405 }
406}