1use scirs2_core::ndarray::{Array1, Array2, ArrayView1, ArrayView2};
6use sklears_core::{
7 error::{Result as SklResult, SklearsError},
8 traits::Estimator,
9 types::Float,
10};
11use std::any::Any;
12use std::collections::{HashMap, HashSet};
13use std::fmt::Debug;
14use std::path::PathBuf;
15use std::sync::{Arc, RwLock};
16
17use super::types::{
18 ComponentConfig, ComponentContext, ComponentSchema, ConfigValue, ExampleRegressor,
19 ExampleScaler, ExampleTransformerFactory, ExampleTransformerPlugin, PluginCapability,
20 PluginConfig, PluginContext, PluginLoader, PluginMetadata, PluginRegistry,
21};
22
23pub trait Plugin: Send + Sync + Debug {
25 fn metadata(&self) -> &PluginMetadata;
27 fn initialize(&mut self, context: &PluginContext) -> SklResult<()>;
29 fn shutdown(&mut self) -> SklResult<()>;
31 fn capabilities(&self) -> Vec<PluginCapability>;
33 fn create_component(
35 &self,
36 component_type: &str,
37 config: &ComponentConfig,
38 ) -> SklResult<Box<dyn PluginComponent>>;
39 fn validate_config(&self, config: &ComponentConfig) -> SklResult<()>;
41 fn get_component_schema(&self, component_type: &str) -> Option<ComponentSchema>;
43}
44pub trait PluginComponent: Send + Sync + Debug {
46 fn component_type(&self) -> &str;
48 fn config(&self) -> &ComponentConfig;
50 fn initialize(&mut self, context: &ComponentContext) -> SklResult<()>;
52 fn clone_component(&self) -> Box<dyn PluginComponent>;
54 fn as_any(&self) -> &dyn Any;
56 fn as_any_mut(&mut self) -> &mut dyn Any;
58}
59pub trait PluginTransformer: PluginComponent {
61 fn fit(
63 &mut self,
64 x: &ArrayView2<'_, Float>,
65 y: Option<&ArrayView1<'_, Float>>,
66 ) -> SklResult<()>;
67 fn transform(&self, x: &ArrayView2<'_, Float>) -> SklResult<Array2<f64>>;
69 fn fit_transform(
71 &mut self,
72 x: &ArrayView2<'_, Float>,
73 y: Option<&ArrayView1<'_, Float>>,
74 ) -> SklResult<Array2<f64>> {
75 self.fit(x, y)?;
76 self.transform(x)
77 }
78 fn is_fitted(&self) -> bool;
80 fn get_feature_names_out(&self, input_features: Option<&[String]>) -> Vec<String>;
82}
83pub trait PluginEstimator: PluginComponent {
85 fn fit(&mut self, x: &ArrayView2<'_, Float>, y: &ArrayView1<'_, Float>) -> SklResult<()>;
87 fn predict(&self, x: &ArrayView2<'_, Float>) -> SklResult<Array1<f64>>;
89 fn predict_proba(&self, x: &ArrayView2<'_, Float>) -> SklResult<Array2<f64>> {
91 Err(SklearsError::InvalidOperation(
92 "predict_proba not implemented for this estimator".to_string(),
93 ))
94 }
95 fn score(&self, x: &ArrayView2<'_, Float>, y: &ArrayView1<'_, Float>) -> SklResult<f64>;
97 fn is_fitted(&self) -> bool;
99 fn feature_importances(&self) -> Option<Array1<f64>> {
101 None
102 }
103}
104pub trait ComponentFactory: Send + Sync + Debug {
106 fn create(
108 &self,
109 component_type: &str,
110 config: &ComponentConfig,
111 ) -> SklResult<Box<dyn PluginComponent>>;
112 fn available_types(&self) -> Vec<String>;
114 fn get_schema(&self, component_type: &str) -> Option<ComponentSchema>;
116}
117#[allow(non_snake_case)]
118#[cfg(test)]
119mod tests {
120 use super::*;
121 use scirs2_core::ndarray::array;
122 #[test]
123 fn test_plugin_registry_creation() {
124 let config = PluginConfig::default();
125 let registry = PluginRegistry::new(config);
126 assert!(registry.list_plugins().unwrap().is_empty());
127 }
128 #[test]
129 fn test_plugin_registration() {
130 let config = PluginConfig::default();
131 let registry = PluginRegistry::new(config);
132 let plugin = Box::new(ExampleTransformerPlugin::new());
133 let factory = Box::new(ExampleTransformerFactory::new());
134 registry
135 .register_plugin("test_plugin", plugin, factory)
136 .unwrap();
137 let plugins = registry.list_plugins().unwrap();
138 assert_eq!(plugins.len(), 1);
139 assert!(plugins.contains(&"test_plugin".to_string()));
140 }
141 #[test]
142 fn test_component_creation() {
143 let config = PluginConfig::default();
144 let registry = PluginRegistry::new(config);
145 let plugin = Box::new(ExampleTransformerPlugin::new());
146 let factory = Box::new(ExampleTransformerFactory::new());
147 registry
148 .register_plugin("test_plugin", plugin, factory)
149 .unwrap();
150 let component_config = ComponentConfig {
151 component_type: "example_scaler".to_string(),
152 parameters: {
153 let mut params = HashMap::new();
154 params.insert("scale_factor".to_string(), ConfigValue::Float(2.0));
155 params
156 },
157 metadata: HashMap::new(),
158 };
159 let component = registry
160 .create_component("test_plugin", "example_scaler", &component_config)
161 .unwrap();
162 assert_eq!(component.component_type(), "example_scaler");
163 }
164 #[test]
165 fn test_example_scaler() {
166 let config = ComponentConfig {
167 component_type: "example_scaler".to_string(),
168 parameters: {
169 let mut params = HashMap::new();
170 params.insert("scale_factor".to_string(), ConfigValue::Float(2.0));
171 params
172 },
173 metadata: HashMap::new(),
174 };
175 let mut scaler = ExampleScaler::new(config);
176 let x = array![[1.0, 2.0], [3.0, 4.0]];
177 scaler.fit(&x.view(), None).unwrap();
178 assert!(scaler.is_fitted());
179 let transformed = scaler.transform(&x.view()).unwrap();
180 assert_eq!(transformed, array![[2.0, 4.0], [6.0, 8.0]]);
181 }
182 #[test]
183 fn test_example_regressor() {
184 let config = ComponentConfig {
185 component_type: "example_regressor".to_string(),
186 parameters: {
187 let mut params = HashMap::new();
188 params.insert("learning_rate".to_string(), ConfigValue::Float(0.001));
189 params
190 },
191 metadata: HashMap::new(),
192 };
193 let mut regressor = ExampleRegressor::new(config);
194 let x = array![[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]];
195 let y = array![3.0, 7.0, 11.0];
196 regressor.fit(&x.view(), &y.view()).unwrap();
197 assert!(regressor.is_fitted());
198 let predictions = regressor.predict(&x.view()).unwrap();
199 assert_eq!(predictions.len(), 3);
200 let score = regressor.score(&x.view(), &y.view()).unwrap();
201 assert!(score > -1.0);
202 }
203 #[test]
204 fn test_plugin_loader() {
205 let config = PluginConfig::default();
206 let registry = PluginRegistry::new(config.clone());
207 let mut loader = PluginLoader::new(config);
208 loader.load_example_plugins(®istry).unwrap();
209 let plugins = registry.list_plugins().unwrap();
210 assert_eq!(plugins.len(), 2);
211 assert!(plugins.contains(&"example_transformer".to_string()));
212 assert!(plugins.contains(&"example_estimator".to_string()));
213 }
214 #[test]
215 fn test_component_schema() {
216 let plugin = ExampleTransformerPlugin::new();
217 let schema = plugin.get_component_schema("example_scaler").unwrap();
218 assert_eq!(schema.name, "ExampleScaler");
219 assert_eq!(schema.required_parameters.len(), 0);
220 assert_eq!(schema.optional_parameters.len(), 1);
221 assert_eq!(schema.optional_parameters[0].name, "scale_factor");
222 }
223 #[test]
224 fn test_plugin_dependencies() {
225 let config = PluginConfig::default();
226 let registry = PluginRegistry::new(config);
227 let metadata = PluginMetadata {
228 name: "Dependent Plugin".to_string(),
229 version: "1.0.0".to_string(),
230 description: "Plugin with dependencies".to_string(),
231 author: "Test".to_string(),
232 license: "MIT".to_string(),
233 min_api_version: "1.0.0".to_string(),
234 dependencies: vec!["nonexistent_plugin".to_string()],
235 capabilities: vec!["transformer".to_string()],
236 tags: vec![],
237 documentation_url: None,
238 source_url: None,
239 };
240 let plugin = ExampleTransformerPlugin::with_metadata(metadata);
241 let factory = Box::new(ExampleTransformerFactory::new());
242 let result = registry.register_plugin("dependent_plugin", Box::new(plugin), factory);
243 assert!(result.is_err());
244 }
245}
246pub mod advanced_plugin_system {
248 use super::{
249 Arc, Debug, HashMap, HashSet, PathBuf, PluginConfig, PluginLoader, PluginRegistry, RwLock,
250 SklResult, SklearsError,
251 };
252 use std::sync::atomic::{AtomicBool, Ordering};
253 use std::thread;
254 use std::time::{Duration, SystemTime};
255 pub struct AdvancedPluginManager {
257 registry: Arc<PluginRegistry>,
258 loader: PluginLoader,
259 watcher: Option<PluginWatcher>,
260 version_manager: VersionManager,
261 security_manager: SecurityManager,
262 performance_monitor: PerformanceMonitor,
263 marketplace: PluginMarketplace,
264 }
265 pub struct PluginWatcher {
267 watched_dirs: Vec<PathBuf>,
268 running: Arc<AtomicBool>,
269 poll_interval: Duration,
270 }
271 #[derive(Debug)]
273 pub struct VersionManager {
274 installed_versions: HashMap<String, Vec<SemanticVersion>>,
275 active_versions: HashMap<String, SemanticVersion>,
276 compatibility_matrix: HashMap<String, Vec<VersionConstraint>>,
277 }
278 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
280 pub struct SemanticVersion {
281 pub major: u32,
282 pub minor: u32,
283 pub patch: u32,
284 pub pre_release: Option<String>,
285 pub build_metadata: Option<String>,
286 }
287 #[derive(Debug, Clone)]
289 pub struct VersionConstraint {
290 pub plugin_name: String,
291 pub constraint_type: ConstraintType,
292 pub version: SemanticVersion,
293 }
294 #[derive(Debug, Clone, PartialEq)]
296 pub enum ConstraintType {
297 Exact,
299 GreaterThan,
301 GreaterOrEqual,
303 LessThan,
305 LessOrEqual,
307 Compatible,
309 Tilde,
311 }
312 #[derive(Debug)]
314 pub struct SecurityManager {
315 sandbox_enabled: bool,
316 allowed_capabilities: HashSet<String>,
317 security_policies: HashMap<String, SecurityPolicy>,
318 threat_detection: ThreatDetector,
319 }
320 #[derive(Debug, Clone)]
322 pub struct SecurityPolicy {
323 pub plugin_name: String,
324 pub allowed_operations: HashSet<PluginOperation>,
325 pub resource_limits: SecurityResourceLimits,
326 pub network_access: NetworkAccess,
327 pub file_system_access: FileSystemAccess,
328 }
329 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
331 pub enum PluginOperation {
332 ReadData,
334 WriteData,
336 NetworkRequest,
338 FileRead,
340 FileWrite,
342 ProcessSpawn,
344 SystemCall,
346 DatabaseAccess,
348 EnvironmentAccess,
350 }
351 #[derive(Debug, Clone)]
353 pub struct SecurityResourceLimits {
354 pub max_memory: Option<usize>,
355 pub max_cpu_time: Option<Duration>,
356 pub max_network_bandwidth: Option<usize>,
357 pub max_file_descriptors: Option<usize>,
358 }
359 #[derive(Debug, Clone)]
361 pub enum NetworkAccess {
362 None,
363 Limited(Vec<String>),
365 Full,
367 }
368 #[derive(Debug, Clone)]
370 pub enum FileSystemAccess {
371 None,
372 ReadOnly(Vec<PathBuf>),
374 Limited(Vec<PathBuf>),
376 Full,
378 }
379 #[derive(Debug)]
381 pub struct ThreatDetector {
382 suspicious_patterns: Vec<ThreatPattern>,
383 monitoring_enabled: bool,
384 alert_callback: Option<fn(&ThreatAlert)>,
385 }
386 #[derive(Debug, Clone)]
388 pub struct ThreatPattern {
389 pub pattern_type: ThreatType,
390 pub pattern: String,
391 pub severity: ThreatSeverity,
392 pub description: String,
393 }
394 #[derive(Debug, Clone, PartialEq)]
396 pub enum ThreatType {
397 SuspiciousCode,
399 UnauthorizedAccess,
401 ResourceAbuse,
403 DataExfiltration,
405 MaliciousPayload,
407 }
408 #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
410 pub enum ThreatSeverity {
411 Low,
412 Medium,
413 High,
414 Critical,
415 }
416 #[derive(Debug)]
418 pub struct ThreatAlert {
419 pub plugin_name: String,
420 pub threat_type: ThreatType,
421 pub severity: ThreatSeverity,
422 pub description: String,
423 pub timestamp: SystemTime,
424 pub details: HashMap<String, String>,
425 }
426 #[derive(Debug)]
428 pub struct PerformanceMonitor {
429 metrics: Arc<RwLock<HashMap<String, PluginMetrics>>>,
430 monitoring_enabled: bool,
431 collection_interval: Duration,
432 }
433 #[derive(Debug, Clone)]
435 pub struct PluginMetrics {
436 pub plugin_name: String,
437 pub execution_count: u64,
438 pub total_execution_time: Duration,
439 pub average_execution_time: Duration,
440 pub memory_usage: MemoryUsageStats,
441 pub error_rate: f64,
442 pub last_execution: Option<SystemTime>,
443 }
444 #[derive(Debug, Clone)]
446 pub struct MemoryUsageStats {
447 pub current_usage: usize,
448 pub peak_usage: usize,
449 pub average_usage: usize,
450 pub allocation_count: u64,
451 }
452 #[derive(Debug)]
454 pub struct PluginMarketplace {
455 repositories: Vec<PluginRepository>,
456 cache: Arc<RwLock<HashMap<String, MarketplaceEntry>>>,
457 update_interval: Duration,
458 last_update: Option<SystemTime>,
459 }
460 #[derive(Debug, Clone)]
462 pub struct PluginRepository {
463 pub url: String,
464 pub name: String,
465 pub auth_token: Option<String>,
466 pub trusted: bool,
467 pub priority: u32,
468 }
469 #[derive(Debug, Clone)]
471 pub struct MarketplaceEntry {
472 pub plugin_name: String,
473 pub versions: Vec<PluginVersion>,
474 pub description: String,
475 pub tags: Vec<String>,
476 pub downloads: u64,
477 pub rating: f64,
478 pub last_updated: SystemTime,
479 }
480 #[derive(Debug, Clone)]
482 pub struct PluginVersion {
483 pub version: SemanticVersion,
484 pub download_url: String,
485 pub checksum: String,
486 pub size: usize,
487 pub release_notes: String,
488 pub compatibility: Vec<String>,
489 }
490 impl AdvancedPluginManager {
491 pub fn new(config: PluginConfig) -> SklResult<Self> {
493 let registry = Arc::new(PluginRegistry::new(config.clone()));
494 let loader = PluginLoader::new(config.clone());
495 let version_manager = VersionManager::new();
496 let security_manager = SecurityManager::new(config.sandbox);
497 let performance_monitor = PerformanceMonitor::new();
498 let marketplace = PluginMarketplace::new();
499 let watcher = if config.auto_load {
500 Some(PluginWatcher::new(config.plugin_dirs))
501 } else {
502 None
503 };
504 Ok(Self {
505 registry,
506 loader,
507 watcher,
508 version_manager,
509 security_manager,
510 performance_monitor,
511 marketplace,
512 })
513 }
514 pub fn start(&mut self) -> SklResult<()> {
516 self.loader.load_plugins(&self.registry)?;
517 self.registry.initialize_all()?;
518 if let Some(ref mut watcher) = self.watcher {
519 watcher.start(Arc::clone(&self.registry))?;
520 }
521 self.performance_monitor.start_monitoring()?;
522 self.marketplace.update_cache()?;
523 Ok(())
524 }
525 pub fn stop(&mut self) -> SklResult<()> {
527 if let Some(ref mut watcher) = self.watcher {
528 watcher.stop();
529 }
530 self.performance_monitor.stop_monitoring()?;
531 self.registry.shutdown_all()?;
532 Ok(())
533 }
534 pub fn install_from_marketplace(
536 &mut self,
537 plugin_name: &str,
538 version: Option<&SemanticVersion>,
539 ) -> SklResult<()> {
540 let entry = self.marketplace.find_plugin(plugin_name)?;
541 let target_version = version.unwrap_or(&entry.versions[0].version);
542 self.security_manager
543 .validate_plugin_security(plugin_name)?;
544 let plugin_data = self
545 .marketplace
546 .download_plugin(plugin_name, target_version)?;
547 self.security_manager.scan_plugin(&plugin_data)?;
548 self.version_manager
549 .install_version(plugin_name, target_version.clone())?;
550 Ok(())
551 }
552 pub fn upgrade_plugin(
554 &mut self,
555 plugin_name: &str,
556 target_version: &SemanticVersion,
557 ) -> SklResult<()> {
558 self.version_manager
559 .check_upgrade_compatibility(plugin_name, target_version)?;
560 self.registry.unregister_plugin(plugin_name)?;
561 self.install_from_marketplace(plugin_name, Some(target_version))?;
562 Ok(())
563 }
564 #[must_use]
566 pub fn get_plugin_metrics(&self, plugin_name: &str) -> Option<PluginMetrics> {
567 self.performance_monitor.get_metrics(plugin_name)
568 }
569 #[must_use]
571 pub fn get_security_report(&self, plugin_name: &str) -> SecurityReport {
572 self.security_manager.generate_report(plugin_name)
573 }
574 #[must_use]
576 pub fn search_marketplace(&self, query: &str, tags: &[String]) -> Vec<MarketplaceEntry> {
577 self.marketplace.search(query, tags)
578 }
579 }
580 #[derive(Debug)]
582 pub struct SecurityReport {
583 pub plugin_name: String,
584 pub security_level: SecurityLevel,
585 pub violations: Vec<SecurityViolation>,
586 pub recommendations: Vec<String>,
587 pub last_scan: Option<SystemTime>,
588 }
589 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
591 pub enum SecurityLevel {
592 Safe,
594 LowRisk,
596 MediumRisk,
598 HighRisk,
600 Critical,
602 }
603 #[derive(Debug)]
605 pub struct SecurityViolation {
606 pub violation_type: ViolationType,
607 pub description: String,
608 pub severity: ThreatSeverity,
609 pub detected_at: SystemTime,
610 }
611 #[derive(Debug)]
613 pub enum ViolationType {
614 UnauthorizedFileAccess,
616 SuspiciousNetworkActivity,
618 ExcessiveResourceUsage,
620 PolicyViolation,
622 MaliciousCode,
624 }
625 impl PluginWatcher {
626 #[must_use]
627 pub fn new(dirs: Vec<PathBuf>) -> Self {
628 Self {
629 watched_dirs: dirs,
630 running: Arc::new(AtomicBool::new(false)),
631 poll_interval: Duration::from_secs(5),
632 }
633 }
634 pub fn start(&mut self, registry: Arc<PluginRegistry>) -> SklResult<()> {
635 self.running.store(true, Ordering::SeqCst);
636 let running = Arc::clone(&self.running);
637 let dirs = self.watched_dirs.clone();
638 let interval = self.poll_interval;
639 thread::spawn(move || {
640 while running.load(Ordering::SeqCst) {
641 for dir in &dirs {
642 if dir.exists() {}
643 }
644 thread::sleep(interval);
645 }
646 });
647 Ok(())
648 }
649 pub fn stop(&mut self) {
650 self.running.store(false, Ordering::SeqCst);
651 }
652 }
653 impl Default for VersionManager {
654 fn default() -> Self {
655 Self::new()
656 }
657 }
658 impl VersionManager {
659 #[must_use]
660 pub fn new() -> Self {
661 Self {
662 installed_versions: HashMap::new(),
663 active_versions: HashMap::new(),
664 compatibility_matrix: HashMap::new(),
665 }
666 }
667 pub fn install_version(
668 &mut self,
669 plugin_name: &str,
670 version: SemanticVersion,
671 ) -> SklResult<()> {
672 self.installed_versions
673 .entry(plugin_name.to_string())
674 .or_default()
675 .push(version.clone());
676 self.active_versions
677 .insert(plugin_name.to_string(), version);
678 Ok(())
679 }
680 pub fn check_upgrade_compatibility(
681 &self,
682 plugin_name: &str,
683 target_version: &SemanticVersion,
684 ) -> SklResult<()> {
685 if let Some(constraints) = self.compatibility_matrix.get(plugin_name) {
686 for constraint in constraints {
687 if !self.version_satisfies_constraint(target_version, constraint) {
688 return Err(SklearsError::InvalidInput(format!(
689 "Version {} does not satisfy constraint {:?}",
690 self.version_to_string(target_version),
691 constraint
692 )));
693 }
694 }
695 }
696 Ok(())
697 }
698 fn version_satisfies_constraint(
699 &self,
700 version: &SemanticVersion,
701 constraint: &VersionConstraint,
702 ) -> bool {
703 match constraint.constraint_type {
704 ConstraintType::Exact => version == &constraint.version,
705 ConstraintType::GreaterThan => version > &constraint.version,
706 ConstraintType::GreaterOrEqual => version >= &constraint.version,
707 ConstraintType::LessThan => version < &constraint.version,
708 ConstraintType::LessOrEqual => version <= &constraint.version,
709 ConstraintType::Compatible => {
710 version.major == constraint.version.major && version >= &constraint.version
711 }
712 ConstraintType::Tilde => {
713 version.major == constraint.version.major
714 && version.minor == constraint.version.minor
715 && version >= &constraint.version
716 }
717 }
718 }
719 fn version_to_string(&self, version: &SemanticVersion) -> String {
720 format!("{}.{}.{}", version.major, version.minor, version.patch)
721 }
722 }
723 impl SecurityManager {
724 #[must_use]
725 pub fn new(sandbox_enabled: bool) -> Self {
726 Self {
727 sandbox_enabled,
728 allowed_capabilities: HashSet::new(),
729 security_policies: HashMap::new(),
730 threat_detection: ThreatDetector::new(),
731 }
732 }
733 pub fn validate_plugin_security(&self, plugin_name: &str) -> SklResult<()> {
734 if let Some(policy) = self.security_policies.get(plugin_name) {
735 Ok(())
736 } else {
737 Ok(())
738 }
739 }
740 pub fn scan_plugin(&self, plugin_data: &[u8]) -> SklResult<()> {
741 self.threat_detection.scan_data(plugin_data)
742 }
743 #[must_use]
744 pub fn generate_report(&self, plugin_name: &str) -> SecurityReport {
745 SecurityReport {
747 plugin_name: plugin_name.to_string(),
748 security_level: SecurityLevel::Safe,
749 violations: Vec::new(),
750 recommendations: Vec::new(),
751 last_scan: Some(SystemTime::now()),
752 }
753 }
754 }
755 impl Default for ThreatDetector {
756 fn default() -> Self {
757 Self::new()
758 }
759 }
760 impl ThreatDetector {
761 #[must_use]
762 pub fn new() -> Self {
763 Self {
764 suspicious_patterns: Vec::new(),
765 monitoring_enabled: true,
766 alert_callback: None,
767 }
768 }
769 pub fn scan_data(&self, data: &[u8]) -> SklResult<()> {
770 let data_str = String::from_utf8_lossy(data);
771 for pattern in &self.suspicious_patterns {
772 if data_str.contains(&pattern.pattern) {
773 let alert = ThreatAlert {
774 plugin_name: "unknown".to_string(),
775 threat_type: pattern.pattern_type.clone(),
776 severity: pattern.severity.clone(),
777 description: pattern.description.clone(),
778 timestamp: SystemTime::now(),
779 details: HashMap::new(),
780 };
781 if let Some(callback) = self.alert_callback {
782 callback(&alert);
783 }
784 if pattern.severity >= ThreatSeverity::High {
785 return Err(SklearsError::InvalidInput(format!(
786 "Security threat detected: {}",
787 pattern.description
788 )));
789 }
790 }
791 }
792 Ok(())
793 }
794 }
795 impl Default for PerformanceMonitor {
796 fn default() -> Self {
797 Self::new()
798 }
799 }
800 impl PerformanceMonitor {
801 #[must_use]
802 pub fn new() -> Self {
803 Self {
804 metrics: Arc::new(RwLock::new(HashMap::new())),
805 monitoring_enabled: false,
806 collection_interval: Duration::from_secs(60),
807 }
808 }
809 pub fn start_monitoring(&mut self) -> SklResult<()> {
810 self.monitoring_enabled = true;
811 Ok(())
812 }
813 pub fn stop_monitoring(&mut self) -> SklResult<()> {
814 self.monitoring_enabled = false;
815 Ok(())
816 }
817 #[must_use]
818 pub fn get_metrics(&self, plugin_name: &str) -> Option<PluginMetrics> {
819 self.metrics.read().ok()?.get(plugin_name).cloned()
820 }
821 pub fn record_execution(&self, plugin_name: &str, execution_time: Duration) {
822 if let Ok(mut metrics) = self.metrics.write() {
823 let plugin_metrics =
824 metrics
825 .entry(plugin_name.to_string())
826 .or_insert_with(|| PluginMetrics {
827 plugin_name: plugin_name.to_string(),
828 execution_count: 0,
829 total_execution_time: Duration::from_secs(0),
830 average_execution_time: Duration::from_secs(0),
831 memory_usage: MemoryUsageStats {
832 current_usage: 0,
833 peak_usage: 0,
834 average_usage: 0,
835 allocation_count: 0,
836 },
837 error_rate: 0.0,
838 last_execution: None,
839 });
840 plugin_metrics.execution_count += 1;
841 plugin_metrics.total_execution_time += execution_time;
842 plugin_metrics.average_execution_time =
843 plugin_metrics.total_execution_time / plugin_metrics.execution_count as u32;
844 plugin_metrics.last_execution = Some(SystemTime::now());
845 }
846 }
847 }
848 impl Default for PluginMarketplace {
849 fn default() -> Self {
850 Self::new()
851 }
852 }
853 impl PluginMarketplace {
854 #[must_use]
855 pub fn new() -> Self {
856 Self {
857 repositories: Vec::new(),
858 cache: Arc::new(RwLock::new(HashMap::new())),
859 update_interval: Duration::from_secs(3600),
860 last_update: None,
861 }
862 }
863 pub fn add_repository(&mut self, repository: PluginRepository) {
864 self.repositories.push(repository);
865 }
866 pub fn update_cache(&mut self) -> SklResult<()> {
867 self.last_update = Some(SystemTime::now());
868 Ok(())
869 }
870 pub fn find_plugin(&self, plugin_name: &str) -> SklResult<MarketplaceEntry> {
871 if let Ok(cache) = self.cache.read() {
872 cache.get(plugin_name).cloned().ok_or_else(|| {
873 SklearsError::InvalidInput(format!(
874 "Plugin {plugin_name} not found in marketplace"
875 ))
876 })
877 } else {
878 Err(SklearsError::InvalidOperation(
879 "Failed to read marketplace cache".to_string(),
880 ))
881 }
882 }
883 pub fn download_plugin(
884 &self,
885 _plugin_name: &str,
886 _version: &SemanticVersion,
887 ) -> SklResult<Vec<u8>> {
888 Ok(vec![])
889 }
890 #[must_use]
891 pub fn search(&self, query: &str, tags: &[String]) -> Vec<MarketplaceEntry> {
892 if let Ok(cache) = self.cache.read() {
893 cache
894 .values()
895 .filter(|entry| {
896 entry.plugin_name.contains(query)
897 || entry.description.contains(query)
898 || tags.iter().any(|tag| entry.tags.contains(tag))
899 })
900 .cloned()
901 .collect()
902 } else {
903 Vec::new()
904 }
905 }
906 }
907 impl SemanticVersion {
908 #[must_use]
909 pub fn new(major: u32, minor: u32, patch: u32) -> Self {
910 Self {
911 major,
912 minor,
913 patch,
914 pre_release: None,
915 build_metadata: None,
916 }
917 }
918 pub fn parse(version_str: &str) -> SklResult<Self> {
919 let parts: Vec<&str> = version_str.split('.').collect();
920 if parts.len() < 3 {
921 return Err(SklearsError::InvalidInput(
922 "Invalid version format".to_string(),
923 ));
924 }
925 let major = parts[0]
926 .parse()
927 .map_err(|_| SklearsError::InvalidInput("Invalid major version".to_string()))?;
928 let minor = parts[1]
929 .parse()
930 .map_err(|_| SklearsError::InvalidInput("Invalid minor version".to_string()))?;
931 let patch = parts[2]
932 .parse()
933 .map_err(|_| SklearsError::InvalidInput("Invalid patch version".to_string()))?;
934 Ok(Self::new(major, minor, patch))
935 }
936 }
937}