automapper_validation/eval/
registry.rs1use std::collections::HashMap;
4use std::sync::{Arc, RwLock};
5
6use super::evaluator::ConditionEvaluator;
7
8pub struct EvaluatorRegistry {
17 evaluators: RwLock<HashMap<(String, String), Arc<dyn ConditionEvaluator>>>,
18}
19
20impl EvaluatorRegistry {
21 pub fn new() -> Self {
23 Self {
24 evaluators: RwLock::new(HashMap::new()),
25 }
26 }
27
28 pub fn register<E: ConditionEvaluator + 'static>(&self, evaluator: E) {
32 let key = (
33 evaluator.message_type().to_string(),
34 evaluator.format_version().to_string(),
35 );
36 self.evaluators
37 .write()
38 .expect("registry lock poisoned")
39 .insert(key, Arc::new(evaluator));
40 }
41
42 pub fn register_as<E: ConditionEvaluator + 'static>(
48 &self,
49 evaluator: E,
50 message_type: &str,
51 format_version: &str,
52 ) {
53 let key = (message_type.to_string(), format_version.to_string());
54 self.evaluators
55 .write()
56 .expect("registry lock poisoned")
57 .insert(key, Arc::new(evaluator));
58 }
59
60 pub fn register_arc(&self, evaluator: Arc<dyn ConditionEvaluator>) {
62 let key = (
63 evaluator.message_type().to_string(),
64 evaluator.format_version().to_string(),
65 );
66 self.evaluators
67 .write()
68 .expect("registry lock poisoned")
69 .insert(key, evaluator);
70 }
71
72 pub fn get(
76 &self,
77 message_type: &str,
78 format_version: &str,
79 ) -> Option<Arc<dyn ConditionEvaluator>> {
80 self.evaluators
81 .read()
82 .expect("registry lock poisoned")
83 .get(&(message_type.to_string(), format_version.to_string()))
84 .cloned()
85 }
86
87 pub fn get_or_err(
89 &self,
90 message_type: &str,
91 format_version: &str,
92 ) -> Result<Arc<dyn ConditionEvaluator>, crate::error::ValidationError> {
93 self.get(message_type, format_version).ok_or_else(|| {
94 crate::error::ValidationError::NoEvaluator {
95 message_type: message_type.to_string(),
96 format_version: format_version.to_string(),
97 }
98 })
99 }
100
101 pub fn registered_keys(&self) -> Vec<(String, String)> {
103 self.evaluators
104 .read()
105 .expect("registry lock poisoned")
106 .keys()
107 .cloned()
108 .collect()
109 }
110
111 pub fn clear(&self) {
113 self.evaluators
114 .write()
115 .expect("registry lock poisoned")
116 .clear();
117 }
118}
119
120impl Default for EvaluatorRegistry {
121 fn default() -> Self {
122 Self::new()
123 }
124}
125
126#[cfg(test)]
127mod tests {
128 use super::super::context::EvaluationContext;
129 use super::super::evaluator::ConditionResult;
130 use super::*;
131
132 struct TestEvaluator {
134 msg_type: String,
135 fmt_version: String,
136 }
137
138 impl TestEvaluator {
139 fn new(msg_type: &str, fmt_version: &str) -> Self {
140 Self {
141 msg_type: msg_type.to_string(),
142 fmt_version: fmt_version.to_string(),
143 }
144 }
145 }
146
147 impl ConditionEvaluator for TestEvaluator {
148 fn evaluate(&self, _condition: u32, _ctx: &EvaluationContext) -> ConditionResult {
149 ConditionResult::Unknown
150 }
151 fn is_external(&self, _condition: u32) -> bool {
152 false
153 }
154 fn message_type(&self) -> &str {
155 &self.msg_type
156 }
157 fn format_version(&self) -> &str {
158 &self.fmt_version
159 }
160 }
161
162 #[test]
163 fn test_register_and_get() {
164 let registry = EvaluatorRegistry::new();
165 registry.register(TestEvaluator::new("UTILMD", "FV2510"));
166
167 let eval = registry.get("UTILMD", "FV2510");
168 assert!(eval.is_some());
169 assert_eq!(eval.unwrap().message_type(), "UTILMD");
170 }
171
172 #[test]
173 fn test_get_nonexistent_returns_none() {
174 let registry = EvaluatorRegistry::new();
175 assert!(registry.get("UTILMD", "FV2510").is_none());
176 }
177
178 #[test]
179 fn test_get_or_err_returns_error() {
180 let registry = EvaluatorRegistry::new();
181 let result = registry.get_or_err("UTILMD", "FV2510");
182 assert!(result.is_err());
183 }
184
185 #[test]
186 fn test_register_overwrites() {
187 let registry = EvaluatorRegistry::new();
188 registry.register(TestEvaluator::new("UTILMD", "FV2510"));
189 registry.register(TestEvaluator::new("UTILMD", "FV2510"));
190
191 let keys = registry.registered_keys();
192 assert_eq!(keys.len(), 1);
193 }
194
195 #[test]
196 fn test_multiple_registrations() {
197 let registry = EvaluatorRegistry::new();
198 registry.register(TestEvaluator::new("UTILMD", "FV2504"));
199 registry.register(TestEvaluator::new("UTILMD", "FV2510"));
200 registry.register(TestEvaluator::new("ORDERS", "FV2510"));
201
202 let keys = registry.registered_keys();
203 assert_eq!(keys.len(), 3);
204
205 assert!(registry.get("UTILMD", "FV2504").is_some());
206 assert!(registry.get("UTILMD", "FV2510").is_some());
207 assert!(registry.get("ORDERS", "FV2510").is_some());
208 assert!(registry.get("ORDERS", "FV2504").is_none());
209 }
210
211 #[test]
212 fn test_clear() {
213 let registry = EvaluatorRegistry::new();
214 registry.register(TestEvaluator::new("UTILMD", "FV2510"));
215 assert!(!registry.registered_keys().is_empty());
216
217 registry.clear();
218 assert!(registry.registered_keys().is_empty());
219 }
220
221 #[test]
222 fn test_register_arc() {
223 let registry = EvaluatorRegistry::new();
224 let eval: Arc<dyn ConditionEvaluator> = Arc::new(TestEvaluator::new("UTILMD", "FV2510"));
225 registry.register_arc(eval);
226
227 assert!(registry.get("UTILMD", "FV2510").is_some());
228 }
229}