Skip to main content

fraiseql_core/validation/
elo_rust_integration.rs

1//! Elo Rust target integration for compiled validators.
2//!
3//! Provides infrastructure for compiling Elo expressions to Rust validators,
4//! caching compiled validators, and executing them with <1µs latency targets.
5//!
6//! Elo is an expression language by Bernard Lambeau: <https://elo-lang.org/>
7
8use std::{collections::HashMap, sync::Arc};
9
10use parking_lot::RwLock;
11
12/// Configuration for the Rust validator registry
13#[derive(Debug, Clone)]
14pub struct RustValidatorRegistryConfig {
15    /// Enable ELO Rust validator compilation and caching
16    pub enabled:          bool,
17    /// Cache compiled validators for reuse
18    pub cache_validators: bool,
19    /// Maximum number of validators to cache
20    pub max_cache_size:   usize,
21}
22
23impl Default for RustValidatorRegistryConfig {
24    fn default() -> Self {
25        Self {
26            enabled:          true,
27            cache_validators: true,
28            max_cache_size:   1000,
29        }
30    }
31}
32
33/// A single ELO Rust validator with generated code
34#[derive(Debug, Clone)]
35pub struct EloRustValidator {
36    /// Name/identifier of the validator
37    pub name:           String,
38    /// ELO expression source
39    pub elo_expression: String,
40    /// Generated Rust code (if compiled)
41    pub generated_code: Option<String>,
42}
43
44/// Registry for managing ELO Rust validators
45#[derive(Clone)]
46pub struct RustValidatorRegistry {
47    config:     Arc<RustValidatorRegistryConfig>,
48    validators: Arc<RwLock<HashMap<String, EloRustValidator>>>,
49}
50
51impl RustValidatorRegistry {
52    /// Create a new validator registry with the given configuration
53    pub fn new(config: RustValidatorRegistryConfig) -> Self {
54        Self {
55            config:     Arc::new(config),
56            validators: Arc::new(RwLock::new(HashMap::new())),
57        }
58    }
59
60    /// Register a new validator
61    pub fn register(&self, validator: EloRustValidator) {
62        let mut validators = self.validators.write();
63        validators.insert(validator.name.clone(), validator);
64    }
65
66    /// Get a registered validator by name
67    pub fn get(&self, name: &str) -> Option<EloRustValidator> {
68        let validators = self.validators.read();
69        validators.get(name).cloned()
70    }
71
72    /// Check if a validator exists
73    pub fn exists(&self, name: &str) -> bool {
74        let validators = self.validators.read();
75        validators.contains_key(name)
76    }
77
78    /// Remove a validator by name
79    pub fn remove(&self, name: &str) {
80        let mut validators = self.validators.write();
81        validators.remove(name);
82    }
83
84    /// Get the number of registered validators
85    pub fn count(&self) -> usize {
86        let validators = self.validators.read();
87        validators.len()
88    }
89
90    /// Check if registry is empty
91    pub fn is_empty(&self) -> bool {
92        let validators = self.validators.read();
93        validators.is_empty()
94    }
95
96    /// List all validators
97    pub fn list_all(&self) -> Vec<EloRustValidator> {
98        let validators = self.validators.read();
99        validators.values().cloned().collect()
100    }
101
102    /// Clear all validators
103    pub fn clear(&self) {
104        let mut validators = self.validators.write();
105        validators.clear();
106    }
107
108    /// Check if registry is enabled
109    pub fn is_enabled(&self) -> bool {
110        self.config.enabled
111    }
112
113    /// Get configuration reference
114    pub fn config(&self) -> &RustValidatorRegistryConfig {
115        &self.config
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::*;
122
123    #[test]
124    fn test_config_default() {
125        let config = RustValidatorRegistryConfig::default();
126        assert!(config.enabled);
127        assert!(config.cache_validators);
128        assert_eq!(config.max_cache_size, 1000);
129    }
130
131    #[test]
132    fn test_validator_creation() {
133        let validator = EloRustValidator {
134            name:           "test".to_string(),
135            elo_expression: "x > 0".to_string(),
136            generated_code: None,
137        };
138        assert_eq!(validator.name, "test");
139    }
140
141    #[test]
142    fn test_registry_register_get() {
143        let config = RustValidatorRegistryConfig::default();
144        let registry = RustValidatorRegistry::new(config);
145
146        let validator = EloRustValidator {
147            name:           "test".to_string(),
148            elo_expression: "x > 0".to_string(),
149            generated_code: None,
150        };
151
152        registry.register(validator.clone());
153        let retrieved = registry.get("test");
154        assert!(retrieved.is_some());
155    }
156
157    #[test]
158    fn test_registry_exists() {
159        let config = RustValidatorRegistryConfig::default();
160        let registry = RustValidatorRegistry::new(config);
161
162        let validator = EloRustValidator {
163            name:           "test".to_string(),
164            elo_expression: "x > 0".to_string(),
165            generated_code: None,
166        };
167
168        registry.register(validator);
169        assert!(registry.exists("test"));
170        assert!(!registry.exists("nonexistent"));
171    }
172
173    #[test]
174    fn test_registry_count() {
175        let config = RustValidatorRegistryConfig::default();
176        let registry = RustValidatorRegistry::new(config);
177
178        for i in 0..5 {
179            let validator = EloRustValidator {
180                name:           format!("v{}", i),
181                elo_expression: "true".to_string(),
182                generated_code: None,
183            };
184            registry.register(validator);
185        }
186
187        assert_eq!(registry.count(), 5);
188    }
189
190    #[test]
191    fn test_registry_remove() {
192        let config = RustValidatorRegistryConfig::default();
193        let registry = RustValidatorRegistry::new(config);
194
195        let validator = EloRustValidator {
196            name:           "test".to_string(),
197            elo_expression: "true".to_string(),
198            generated_code: None,
199        };
200
201        registry.register(validator);
202        assert_eq!(registry.count(), 1);
203
204        registry.remove("test");
205        assert_eq!(registry.count(), 0);
206    }
207
208    #[test]
209    fn test_registry_is_enabled() {
210        let config = RustValidatorRegistryConfig {
211            enabled: true,
212            ..Default::default()
213        };
214        let registry = RustValidatorRegistry::new(config);
215        assert!(registry.is_enabled());
216
217        let config2 = RustValidatorRegistryConfig {
218            enabled: false,
219            ..Default::default()
220        };
221        let registry2 = RustValidatorRegistry::new(config2);
222        assert!(!registry2.is_enabled());
223    }
224}