dataforge/customization/
plugins.rs

1//! 插件机制实现
2
3use std::collections::HashMap;
4use std::path::Path;
5use serde_json::Value;
6use crate::error::{DataForgeError, Result};
7use super::{CustomGenerator, ParamType};
8
9/// 插件管理器
10pub struct PluginManager {
11    plugins: HashMap<String, Box<dyn Plugin>>,
12    loaded_paths: Vec<String>,
13}
14
15impl PluginManager {
16    /// 创建新的插件管理器
17    pub fn new() -> Self {
18        Self {
19            plugins: HashMap::new(),
20            loaded_paths: Vec::new(),
21        }
22    }
23
24    /// 加载插件
25    pub fn load_plugin<P>(&mut self, plugin: P) -> Result<()>
26    where
27        P: Plugin + 'static,
28    {
29        let name = plugin.name().to_string();
30        
31        if self.plugins.contains_key(&name) {
32            return Err(DataForgeError::validation(&format!(
33                "Plugin '{}' is already loaded", name
34            )));
35        }
36
37        // 初始化插件
38        plugin.initialize()?;
39        
40        self.plugins.insert(name, Box::new(plugin));
41        Ok(())
42    }
43
44    /// 卸载插件
45    pub fn unload_plugin(&mut self, name: &str) -> Result<()> {
46        if let Some(mut plugin) = self.plugins.remove(name) {
47            plugin.cleanup()?;
48            Ok(())
49        } else {
50            Err(DataForgeError::validation(&format!("Plugin '{}' not found", name)))
51        }
52    }
53
54    /// 获取插件
55    pub fn get_plugin(&self, name: &str) -> Option<&dyn Plugin> {
56        self.plugins.get(name).map(|p| p.as_ref())
57    }
58
59    /// 列出所有插件
60    pub fn list_plugins(&self) -> Vec<PluginInfo> {
61        self.plugins.iter().map(|(name, plugin)| {
62            PluginInfo {
63                name: name.clone(),
64                version: plugin.version().to_string(),
65                description: plugin.description().to_string(),
66                author: plugin.author().to_string(),
67                generators: plugin.generators().iter().map(|g| g.name().to_string()).collect(),
68            }
69        }).collect()
70    }
71
72    /// 从目录加载插件
73    pub fn load_plugins_from_directory<P: AsRef<Path>>(&mut self, dir: P) -> Result<Vec<String>> {
74        let dir_path = dir.as_ref();
75        if !dir_path.exists() || !dir_path.is_dir() {
76            return Err(DataForgeError::validation("Plugin directory does not exist or is not a directory"));
77        }
78
79        let mut loaded_plugins = Vec::new();
80        
81        // 这里应该实现动态库加载逻辑
82        // 由于Rust的动态库加载比较复杂,这里提供一个框架
83        // 实际实现需要使用libloading或类似的crate
84        
85        // 示例:扫描目录中的插件配置文件
86        for entry in std::fs::read_dir(dir_path)? {
87            let entry = entry?;
88            let path = entry.path();
89            
90            if path.extension().and_then(|s| s.to_str()) == Some("plugin") {
91                // 这里应该加载插件配置并实例化插件
92                // 目前只是记录路径
93                if let Some(path_str) = path.to_str() {
94                    self.loaded_paths.push(path_str.to_string());
95                    loaded_plugins.push(path_str.to_string());
96                }
97            }
98        }
99
100        Ok(loaded_plugins)
101    }
102
103    /// 重新加载所有插件
104    pub fn reload_all(&mut self) -> Result<()> {
105        // 卸载所有插件
106        let plugin_names: Vec<String> = self.plugins.keys().cloned().collect();
107        for name in plugin_names {
108            self.unload_plugin(&name)?;
109        }
110
111        // 重新加载
112        let paths = self.loaded_paths.clone();
113        for path in paths {
114            // 这里应该重新加载插件
115            // 目前只是占位符
116            println!("Reloading plugin from: {}", path);
117        }
118
119        Ok(())
120    }
121
122    /// 获取所有生成器
123    pub fn get_all_generators(&self) -> Vec<&dyn CustomGenerator> {
124        let mut generators = Vec::new();
125        
126        for plugin in self.plugins.values() {
127            generators.extend(plugin.generators());
128        }
129        
130        generators
131    }
132}
133
134impl Default for PluginManager {
135    fn default() -> Self {
136        Self::new()
137    }
138}
139
140/// 插件特征
141pub trait Plugin: Send + Sync {
142    /// 插件名称
143    fn name(&self) -> &str;
144    
145    /// 插件版本
146    fn version(&self) -> &str;
147    
148    /// 插件描述
149    fn description(&self) -> &str;
150    
151    /// 插件作者
152    fn author(&self) -> &str;
153    
154    /// 初始化插件
155    fn initialize(&self) -> Result<()> {
156        Ok(())
157    }
158    
159    /// 清理插件
160    fn cleanup(&mut self) -> Result<()> {
161        Ok(())
162    }
163    
164    /// 获取插件提供的生成器
165    fn generators(&self) -> Vec<&dyn CustomGenerator>;
166    
167    /// 插件配置
168    fn config(&self) -> HashMap<String, Value> {
169        HashMap::new()
170    }
171    
172    /// 设置插件配置
173    fn set_config(&mut self, config: HashMap<String, Value>) -> Result<()> {
174        let _ = config;
175        Ok(())
176    }
177}
178
179/// 插件信息
180#[derive(Debug, Clone)]
181pub struct PluginInfo {
182    pub name: String,
183    pub version: String,
184    pub description: String,
185    pub author: String,
186    pub generators: Vec<String>,
187}
188
189/// 示例插件:数学生成器插件
190pub struct MathGeneratorPlugin {
191    name: String,
192    version: String,
193    generators: Vec<Box<dyn CustomGenerator>>,
194}
195
196impl MathGeneratorPlugin {
197    pub fn new() -> Self {
198        let mut plugin = Self {
199            name: "math_generators".to_string(),
200            version: "1.0.0".to_string(),
201            generators: Vec::new(),
202        };
203        
204        // 添加数学相关的生成器
205        plugin.generators.push(Box::new(RandomNumberGenerator::new()));
206        plugin.generators.push(Box::new(MathExpressionGenerator::new()));
207        
208        plugin
209    }
210}
211
212impl Plugin for MathGeneratorPlugin {
213    fn name(&self) -> &str {
214        &self.name
215    }
216
217    fn version(&self) -> &str {
218        &self.version
219    }
220
221    fn description(&self) -> &str {
222        "Provides mathematical data generators"
223    }
224
225    fn author(&self) -> &str {
226        "DataForge Team"
227    }
228
229    fn generators(&self) -> Vec<&dyn CustomGenerator> {
230        self.generators.iter().map(|g| g.as_ref()).collect()
231    }
232}
233
234impl Default for MathGeneratorPlugin {
235    fn default() -> Self {
236        Self::new()
237    }
238}
239
240/// 随机数生成器
241struct RandomNumberGenerator {
242    name: String,
243}
244
245impl RandomNumberGenerator {
246    fn new() -> Self {
247        Self {
248            name: "random_number".to_string(),
249        }
250    }
251}
252
253impl CustomGenerator for RandomNumberGenerator {
254    fn name(&self) -> &str {
255        &self.name
256    }
257
258    fn description(&self) -> &str {
259        "Generates random numbers within specified range"
260    }
261
262    fn generate(&self) -> Result<Value> {
263        use rand::Rng;
264        let mut rng = rand::thread_rng();
265        let number = rng.gen_range(0..=100);
266        Ok(Value::Number(serde_json::Number::from(number)))
267    }
268
269    fn generate_with_params(&self, params: &HashMap<String, Value>) -> Result<Value> {
270        use rand::Rng;
271        let mut rng = rand::thread_rng();
272        
273        let min = params.get("min")
274            .and_then(|v| v.as_i64())
275            .unwrap_or(0);
276            
277        let max = params.get("max")
278            .and_then(|v| v.as_i64())
279            .unwrap_or(100);
280            
281        if min >= max {
282            return Err(DataForgeError::validation("Min must be less than max"));
283        }
284        
285        let number = rng.gen_range(min..=max);
286        Ok(Value::Number(serde_json::Number::from(number)))
287    }
288
289    fn validate_params(&self, params: &HashMap<String, Value>) -> Result<()> {
290        if let (Some(min), Some(max)) = (params.get("min"), params.get("max")) {
291            if let (Some(min_val), Some(max_val)) = (min.as_i64(), max.as_i64()) {
292                if min_val >= max_val {
293                    return Err(DataForgeError::validation("Min must be less than max"));
294                }
295            }
296        }
297        Ok(())
298    }
299
300    fn param_schema(&self) -> HashMap<String, ParamType> {
301        let mut schema = HashMap::new();
302        schema.insert("min".to_string(), ParamType::Integer { min: None, max: None });
303        schema.insert("max".to_string(), ParamType::Integer { min: None, max: None });
304        schema
305    }
306}
307
308/// 数学表达式生成器
309struct MathExpressionGenerator {
310    name: String,
311}
312
313impl MathExpressionGenerator {
314    fn new() -> Self {
315        Self {
316            name: "math_expression".to_string(),
317        }
318    }
319}
320
321impl CustomGenerator for MathExpressionGenerator {
322    fn name(&self) -> &str {
323        &self.name
324    }
325
326    fn description(&self) -> &str {
327        "Generates simple mathematical expressions"
328    }
329
330    fn generate(&self) -> Result<Value> {
331        use rand::Rng;
332        let mut rng = rand::thread_rng();
333        
334        let a = rng.gen_range(1..=100);
335        let b = rng.gen_range(1..=100);
336        let operators = ["+", "-", "*", "/"];
337        let op = operators[rng.gen_range(0..operators.len())];
338        
339        let expression = format!("{} {} {}", a, op, b);
340        Ok(Value::String(expression))
341    }
342
343    fn generate_with_params(&self, params: &HashMap<String, Value>) -> Result<Value> {
344        use rand::Rng;
345        let mut rng = rand::thread_rng();
346        
347        let max_value = params.get("max_value")
348            .and_then(|v| v.as_u64())
349            .unwrap_or(100) as i32;
350            
351        let operators = if let Some(Value::Array(ops)) = params.get("operators") {
352            ops.iter()
353                .filter_map(|v| v.as_str())
354                .collect::<Vec<_>>()
355        } else {
356            vec!["+", "-", "*", "/"]
357        };
358        
359        if operators.is_empty() {
360            return Err(DataForgeError::validation("At least one operator must be specified"));
361        }
362        
363        let a = rng.gen_range(1..=max_value);
364        let b = rng.gen_range(1..=max_value);
365        let op = operators[rng.gen_range(0..operators.len())];
366        
367        let expression = format!("{} {} {}", a, op, b);
368        Ok(Value::String(expression))
369    }
370
371    fn param_schema(&self) -> HashMap<String, ParamType> {
372        let mut schema = HashMap::new();
373        schema.insert("max_value".to_string(), ParamType::Integer { min: Some(1), max: Some(10000) });
374        schema.insert("operators".to_string(), ParamType::Array(Box::new(ParamType::String { max_length: Some(1) })));
375        schema
376    }
377}
378
379#[cfg(test)]
380mod tests {
381    use super::*;
382
383    #[test]
384    fn test_plugin_manager() {
385        let mut manager = PluginManager::new();
386        let plugin = MathGeneratorPlugin::new();
387        
388        assert!(manager.load_plugin(plugin).is_ok());
389        
390        let plugins = manager.list_plugins();
391        assert_eq!(plugins.len(), 1);
392        assert_eq!(plugins[0].name, "math_generators");
393        
394        let generators = manager.get_all_generators();
395        assert_eq!(generators.len(), 2);
396    }
397
398    #[test]
399    fn test_math_plugin() {
400        let plugin = MathGeneratorPlugin::new();
401        
402        assert_eq!(plugin.name(), "math_generators");
403        assert_eq!(plugin.version(), "1.0.0");
404        assert!(!plugin.description().is_empty());
405        
406        let generators = plugin.generators();
407        assert_eq!(generators.len(), 2);
408    }
409
410    #[test]
411    fn test_random_number_generator() {
412        let generator = RandomNumberGenerator::new();
413        
414        let result = generator.generate();
415        assert!(result.is_ok());
416        
417        if let Ok(Value::Number(n)) = result {
418            let val = n.as_i64().unwrap();
419            assert!(val >= 0 && val <= 100);
420        }
421        
422        let mut params = HashMap::new();
423        params.insert("min".to_string(), Value::Number(serde_json::Number::from(10)));
424        params.insert("max".to_string(), Value::Number(serde_json::Number::from(20)));
425        
426        let result = generator.generate_with_params(&params);
427        assert!(result.is_ok());
428        
429        if let Ok(Value::Number(n)) = result {
430            let val = n.as_i64().unwrap();
431            assert!(val >= 10 && val <= 20);
432        }
433    }
434
435    #[test]
436    fn test_math_expression_generator() {
437        let generator = MathExpressionGenerator::new();
438        
439        let result = generator.generate();
440        assert!(result.is_ok());
441        
442        if let Ok(Value::String(expr)) = result {
443            assert!(expr.contains(' '));
444            assert!(expr.chars().any(|c| "+-*/".contains(c)));
445        }
446    }
447
448    #[test]
449    fn test_plugin_unload() {
450        let mut manager = PluginManager::new();
451        let plugin = MathGeneratorPlugin::new();
452        
453        manager.load_plugin(plugin).unwrap();
454        assert_eq!(manager.list_plugins().len(), 1);
455        
456        assert!(manager.unload_plugin("math_generators").is_ok());
457        assert_eq!(manager.list_plugins().len(), 0);
458        
459        assert!(manager.unload_plugin("nonexistent").is_err());
460    }
461}