sklears_core/plugin/mod.rs
1//! Plugin System Module
2//!
3//! This module provides a comprehensive plugin architecture for the SKLears framework,
4//! enabling dynamic loading, validation, and management of machine learning algorithms
5//! and data processing components.
6//!
7//! # Plugin System Architecture
8//!
9//! The plugin system is organized into several key components:
10//!
11//! ## Core Components
12//!
13//! - **[Core Traits](core_traits)**: Foundation traits that all plugins must implement
14//! - **[Types & Configuration](types_config)**: Type-safe parameter handling and plugin metadata
15//! - **[Registry](registry)**: Thread-safe plugin registration and discovery
16//! - **[Loader](loader)**: Dynamic library loading with cross-platform support
17//!
18//! ## Advanced Features
19//!
20//! - **[Factory & Builder](factory_builder)**: Factory patterns for plugin creation
21//! - **[Validation](validation)**: Comprehensive security and quality validation
22//! - **[Security](security)**: Permission management and digital signatures
23//! - **[Discovery & Marketplace](discovery_marketplace)**: Remote plugin discovery and community features
24//! - **[Testing Utilities](testing_utils)**: Complete testing framework for plugin development
25//!
26//! # Quick Start
27//!
28//! ## Creating a Simple Plugin
29//!
30//! ```rust,ignore
31//! use sklears_core::plugin::{Plugin, PluginMetadata, PluginConfig, PluginCategory};
32//! use sklears_core::error::Result;
33//! use std::any::{Any, TypeId};
34//!
35//! #[derive(Debug)]
36//! struct MyAlgorithm {
37//! name: String,
38//! }
39//!
40//! impl Plugin for MyAlgorithm {
41//! fn id(&self) -> &str {
42//! &self.name
43//! }
44//!
45//! fn metadata(&self) -> PluginMetadata {
46//! PluginMetadata {
47//! name: "My Algorithm".to_string(),
48//! version: "1.0.0".to_string(),
49//! description: "An example machine learning algorithm".to_string(),
50//! author: "Your Name".to_string(),
51//! category: PluginCategory::Algorithm,
52//! supported_types: vec![TypeId::of::<f64>()],
53//! ..Default::default()
54//! }
55//! }
56//!
57//! fn initialize(&mut self, _config: &PluginConfig) -> Result<()> {
58//! println!("Initializing {}", self.name);
59//! Ok(())
60//! }
61//!
62//! fn is_compatible(&self, input_type: TypeId) -> bool {
63//! input_type == TypeId::of::<f64>()
64//! }
65//!
66//! fn as_any(&self) -> &dyn Any { self }
67//! fn as_any_mut(&mut self) -> &mut dyn Any { self }
68//! fn validate_config(&self, _config: &PluginConfig) -> Result<()> { Ok(()) }
69//! fn cleanup(&mut self) -> Result<()> { Ok(()) }
70//! }
71//! ```
72//!
73//! ## Using the Plugin Registry
74//!
75//! ```rust,ignore
76//! use sklears_core::plugin::{PluginRegistry, Plugin};
77//!
78//! # use sklears_core::plugin::{PluginMetadata, PluginConfig, PluginCategory};
79//! # use sklears_core::error::Result;
80//! # use std::any::{Any, TypeId};
81//! # #[derive(Debug)]
82//! # struct MyAlgorithm { name: String }
83//! # impl Plugin for MyAlgorithm {
84//! # fn id(&self) -> &str { &self.name }
85//! # fn metadata(&self) -> PluginMetadata {
86//! # PluginMetadata {
87//! # name: "My Algorithm".to_string(),
88//! # version: "1.0.0".to_string(),
89//! # description: "An example algorithm".to_string(),
90//! # author: "Your Name".to_string(),
91//! # category: PluginCategory::Algorithm,
92//! # supported_types: vec![TypeId::of::<f64>()],
93//! # ..Default::default()
94//! # }
95//! # }
96//! # fn initialize(&mut self, _config: &PluginConfig) -> Result<()> { Ok(()) }
97//! # fn is_compatible(&self, input_type: TypeId) -> bool { input_type == TypeId::of::<f64>() }
98//! # fn as_any(&self) -> &dyn Any { self }
99//! # fn as_any_mut(&mut self) -> &mut dyn Any { self }
100//! # fn validate_config(&self, _config: &PluginConfig) -> Result<()> { Ok(()) }
101//! # fn cleanup(&mut self) -> Result<()> { Ok(()) }
102//! # }
103//! fn example() -> Result<(), Box<dyn std::error::Error>> {
104//! let registry = PluginRegistry::new();
105//!
106//! // Register a plugin
107//! let plugin = MyAlgorithm { name: "my_algo".to_string() };
108//! registry.register("my_algo", Box::new(plugin))?;
109//!
110//! // List available plugins
111//! let plugins = registry.list_plugins()?;
112//! println!("Available plugins: {:?}", plugins);
113//!
114//! // Search for plugins
115//! let matches = registry.search_plugins("algorithm")?;
116//! println!("Found {} matching plugins", matches.len());
117//!
118//! Ok(())
119//! }
120//! ```
121//!
122//! ## Building Plugin Configurations
123//!
124//! ```rust,ignore
125//! use sklears_core::plugin::{PluginConfigBuilder, PluginParameter, LogLevel};
126//!
127//! let config = PluginConfigBuilder::new()
128//! .with_parameter("learning_rate", PluginParameter::Float(0.01))
129//! .with_parameter("max_iterations", PluginParameter::Int(1000))
130//! .with_parameter("use_bias", PluginParameter::Bool(true))
131//! .with_threads(4)
132//! .with_memory_limit(1024 * 1024 * 1024) // 1GB
133//! .with_gpu(true)
134//! .with_log_level(LogLevel::Info)
135//! .build();
136//! ```
137//!
138//! ## Dynamic Library Loading
139//!
140//! ```rust,ignore
141//! use sklears_core::plugin::{PluginLoader, PluginRegistry};
142//! use std::sync::Arc;
143//!
144//! # #[cfg(feature = "dynamic_loading")]
145//! fn example() -> Result<(), Box<dyn std::error::Error>> {
146//! let registry = Arc::new(PluginRegistry::new());
147//! let mut loader = PluginLoader::new(registry.clone());
148//!
149//! // Load a single plugin
150//! loader.load_from_library("./plugins/my_plugin.so", "my_plugin")?;
151//!
152//! // Load all plugins from a directory
153//! let loaded = loader.load_from_directory("./plugins/")?;
154//! println!("Loaded {} plugins", loaded.len());
155//!
156//! Ok(())
157//! }
158//! ```
159//!
160//! ## Plugin Validation and Security
161//!
162//! ```rust,ignore
163//! use sklears_core::plugin::{PluginValidator, SecurityPolicy, Permission};
164//!
165//! // Create a validator with custom security policy
166//! let mut validator = PluginValidator::new();
167//! let mut policy = SecurityPolicy::standard();
168//! policy.add_dangerous_permission("network_access".to_string());
169//!
170//! // Validate plugins before loading
171//! # /*
172//! let validation_report = validator.validate_comprehensive(&plugin, &manifest)?;
173//! if validation_report.has_errors() {
174//! println!("Plugin validation failed: {:?}", validation_report.errors);
175//! }
176//! # */
177//! ```
178//!
179//! ## Plugin Discovery and Marketplace
180//!
181//! ```rust,ignore
182//! use sklears_core::plugin::{PluginDiscoveryService, PluginMarketplace, SearchQuery, PluginCategory};
183//!
184//! async fn example() -> Result<(), Box<dyn std::error::Error>> {
185//! let marketplace = PluginMarketplace::new();
186//!
187//! // Get featured plugins
188//! let featured = marketplace.get_featured_plugins().await?;
189//! println!("Featured plugins: {}", featured.len());
190//!
191//! // Search for plugins
192//! let discovery = PluginDiscoveryService::new();
193//! let query = SearchQuery {
194//! text: "classification".to_string(),
195//! category: Some(PluginCategory::Algorithm),
196//! capabilities: vec![],
197//! limit: Some(10),
198//! min_rating: Some(4.0),
199//! };
200//! let results = discovery.search(&query).await?;
201//!
202//! // Install a plugin
203//! if let Some(result) = results.first() {
204//! let install_result = discovery.install_plugin(&result.plugin_id, None).await?;
205//! println!("Installed plugin at: {}", install_result.install_path);
206//! }
207//!
208//! Ok(())
209//! }
210//! ```
211//!
212//! # Testing Plugins
213//!
214//! The plugin system includes comprehensive testing utilities:
215//!
216//! ```rust,ignore
217//! use sklears_core::plugin::{MockPlugin, ValidationTestRunner, PluginTestFixture};
218//!
219//! // Create mock plugins for testing
220//! let mut mock = MockPlugin::new("test_plugin");
221//! mock.set_initialization_error(Some("Test error"));
222//!
223//! // Run comprehensive validation tests
224//! let runner = ValidationTestRunner::new();
225//! let fixture = PluginTestFixture::new();
226//! let manifest = &fixture.create_test_manifests()[0];
227//!
228//! # /*
229//! let report = runner.run_validation_tests(&mock, manifest);
230//! println!("Validation passed: {}", !report.has_errors());
231//! # */
232//! ```
233
234// Core plugin functionality
235pub mod core_traits;
236pub mod loader;
237pub mod registry;
238pub mod types_config;
239
240// Advanced plugin features
241pub mod discovery_marketplace;
242pub mod factory_builder;
243pub mod security;
244pub mod validation;
245
246// Testing and development utilities
247pub mod testing_utils;
248
249// Re-export core traits and types for convenient access
250pub use core_traits::{AlgorithmPlugin, ClusteringPlugin, Plugin, TransformerPlugin};
251
252pub use types_config::{
253 LogLevel, PluginCapability, PluginCategory, PluginConfig, PluginMetadata, PluginParameter,
254 RuntimeSettings,
255};
256
257pub use registry::PluginRegistry;
258
259pub use loader::PluginLoader;
260
261// Factory and builder patterns
262pub use factory_builder::{PluginConfigBuilder, PluginFactory};
263
264// Validation framework
265pub use validation::{
266 ApiUsageInfo, CodeAnalysisInfo, Dependency, PluginManifest, PluginValidator, ValidationCheck,
267 ValidationError, ValidationReport, ValidationResult, ValidationWarning, Vulnerability,
268};
269
270// Security framework
271pub use security::{
272 CertificateInfo, DigitalSignature, Permission, PermissionSet, PublicKeyInfo, PublisherInfo,
273 SecurityPolicy, TrustStore,
274};
275
276// Discovery and marketplace
277pub use discovery_marketplace::{
278 FeaturedPlugin, MarketplaceInfo, MarketplaceSummary, PluginDiscoveryService,
279 PluginInstallResult, PluginMarketplace, PluginRepository, PluginReview, PluginSearchResult,
280 PluginStats, PricingInfo, RepositoryStats, SearchQuery, SubscriptionPeriod, SupportLevel,
281 TrendDirection, TrendingPlugin, UsageUnit,
282};
283
284// Testing utilities
285pub use testing_utils::{
286 CompatibilityTestResult, CompleteTestResult, MockPlugin, PerformanceResult,
287 PluginPerformanceTester, PluginTestFixture, ValidationTestRunner,
288};
289
290// Convenience re-exports for common patterns
291/// Common plugin development imports
292pub mod prelude {
293 pub use super::{
294 AlgorithmPlugin, ClusteringPlugin, LogLevel, Plugin, PluginCapability, PluginCategory,
295 PluginConfig, PluginConfigBuilder, PluginFactory, PluginMetadata, PluginParameter,
296 PluginRegistry, TransformerPlugin,
297 };
298}
299
300/// Security-focused imports for plugin validation
301pub mod security_prelude {
302 pub use super::{
303 DigitalSignature, Permission, PermissionSet, PluginValidator, SecurityPolicy, TrustStore,
304 ValidationReport,
305 };
306}
307
308/// Marketplace and discovery imports
309pub mod marketplace_prelude {
310 pub use super::{
311 FeaturedPlugin, PluginDiscoveryService, PluginMarketplace, PluginRepository, PluginStats,
312 SearchQuery,
313 };
314}
315
316/// Testing utilities imports
317pub mod testing_prelude {
318 pub use super::{
319 CompleteTestResult, MockPlugin, PluginPerformanceTester, PluginTestFixture,
320 ValidationTestRunner,
321 };
322}
323
324// Convenience type aliases for common use cases
325/// Type alias for a boxed plugin instance
326pub type BoxedPlugin = Box<dyn Plugin>;
327
328/// Type alias for plugin validation result
329pub type PluginValidationResult = Result<ValidationReport, crate::error::SklearsError>;
330
331/// Type alias for plugin creation function (for dynamic loading)
332pub type PluginCreateFn = fn() -> BoxedPlugin;
333
334// Module-level documentation and examples
335
336/// # Plugin Development Guide
337///
338/// ## Creating Custom Plugins
339///
340/// To create a custom plugin, implement the `Plugin` trait and any relevant
341/// specialized traits like `AlgorithmPlugin` or `TransformerPlugin`:
342///
343/// ```rust,ignore
344/// use sklears_core::plugin::prelude::*;
345/// use sklears_core::error::Result;
346/// use std::any::{Any, TypeId};
347/// use std::collections::HashMap;
348///
349/// #[derive(Debug)]
350/// struct LinearRegression {
351/// coefficients: Vec`<f64>`,
352/// intercept: f64,
353/// }
354///
355/// impl Plugin for LinearRegression {
356/// fn id(&self) -> &str { "linear_regression" }
357///
358/// fn metadata(&self) -> PluginMetadata {
359/// PluginMetadata {
360/// name: "Linear Regression".to_string(),
361/// version: "1.0.0".to_string(),
362/// description: "Simple linear regression algorithm".to_string(),
363/// author: "SKLears Team".to_string(),
364/// category: PluginCategory::Algorithm,
365/// supported_types: vec![TypeId::of::`<f64>`()],
366/// capabilities: vec![PluginCapability::Parallel],
367/// ..Default::default()
368/// }
369/// }
370///
371/// fn initialize(&mut self, config: &PluginConfig) -> Result<()> {
372/// // Initialize algorithm with configuration
373/// if let Some(param) = config.parameters.get("regularization") {
374/// let reg_strength = param.as_float()?;
375/// println!("Using regularization strength: {}", reg_strength);
376/// }
377/// Ok(())
378/// }
379///
380/// fn is_compatible(&self, input_type: TypeId) -> bool {
381/// input_type == TypeId::of::`<f64>`()
382/// }
383///
384/// fn as_any(&self) -> &dyn Any { self }
385/// fn as_any_mut(&mut self) -> &mut dyn Any { self }
386/// fn validate_config(&self, _config: &PluginConfig) -> Result<()> { Ok(()) }
387/// fn cleanup(&mut self) -> Result<()> { Ok(()) }
388/// }
389/// ```
390///
391/// ## Security Best Practices
392///
393/// When developing plugins, follow these security guidelines:
394///
395/// 1. **Minimize Permissions**: Only request permissions your plugin actually needs
396/// 2. **Validate Inputs**: Always validate configuration parameters and input data
397/// 3. **Handle Errors Gracefully**: Don't expose sensitive information in error messages
398/// 4. **Use Safe APIs**: Avoid unsafe code blocks unless absolutely necessary
399/// 5. **Sign Your Plugins**: Use digital signatures for distribution
400///
401/// ## Performance Considerations
402///
403/// - Implement efficient algorithms with O(n log n) or better complexity where possible
404/// - Use SIMD operations for numerical computations when available
405/// - Minimize memory allocations in hot paths
406/// - Support parallel processing through the `Parallel` capability
407/// - Use lazy initialization for expensive resources
408///
409/// ## Testing Your Plugins
410///
411/// Use the comprehensive testing framework:
412///
413/// ```rust,ignore
414/// use sklears_core::plugin::testing_prelude::*;
415///
416/// #[test]
417/// fn test_my_plugin() {
418/// let mut mock = MockPlugin::new("test_plugin");
419/// let runner = ValidationTestRunner::new();
420/// let fixture = PluginTestFixture::new();
421///
422/// // Run comprehensive tests
423/// let manifest = &fixture.create_test_manifests()[0];
424/// let mut test_results = runner.run_complete_test_suite(&mut mock, manifest);
425///
426/// assert!(test_results.test_passed);
427/// assert!(test_results.overall_score >= 80);
428/// }
429/// ```
430#[allow(non_snake_case)]
431#[cfg(test)]
432mod integration_tests {
433 use super::*;
434 use std::any::TypeId;
435
436 #[test]
437 fn test_plugin_system_integration() {
438 // Test basic plugin creation and registration
439 let registry = PluginRegistry::new();
440 let mock = testing_utils::MockPlugin::new("integration_test");
441
442 assert!(registry
443 .register("integration_test", Box::new(mock))
444 .is_ok());
445
446 let plugins = registry.list_plugins().unwrap();
447 assert!(plugins.contains(&"integration_test".to_string()));
448 }
449
450 #[test]
451 fn test_plugin_configuration_builder() {
452 let config = PluginConfigBuilder::new()
453 .with_parameter("test_param", PluginParameter::Float(1.0))
454 .with_threads(2)
455 .with_gpu(false)
456 .build();
457
458 assert_eq!(config.parameters.len(), 1);
459 assert_eq!(config.runtime_settings.num_threads, Some(2));
460 assert!(!config.runtime_settings.use_gpu);
461 }
462
463 #[test]
464 fn test_security_policy_levels() {
465 let strict = SecurityPolicy::strict();
466 let standard = SecurityPolicy::standard();
467 let permissive = SecurityPolicy::permissive();
468
469 assert!(strict.require_signatures);
470 assert!(standard.require_signatures);
471 assert!(!permissive.require_signatures);
472
473 assert!(!strict.allow_unsafe_code);
474 assert!(!standard.allow_unsafe_code);
475 assert!(permissive.allow_unsafe_code);
476 }
477
478 #[test]
479 fn test_plugin_validation_framework() {
480 let validator = PluginValidator::new();
481 let fixture = PluginTestFixture::new();
482 let mock = testing_utils::MockPlugin::new("validation_test");
483 let manifest = &fixture.create_test_manifests()[3]; // Signed manifest for validation
484
485 let report = validator.validate_comprehensive(&mock, manifest).unwrap();
486 assert!(!report.has_errors());
487 }
488
489 #[test]
490 fn test_permission_system() {
491 let fs_read = Permission::FileSystemRead;
492 let fs_write = Permission::FileSystemWrite;
493 let sys_cmd = Permission::SystemCommands;
494
495 assert_eq!(fs_read.risk_level(), 2);
496 assert_eq!(fs_write.risk_level(), 3);
497 assert_eq!(sys_cmd.risk_level(), 5);
498
499 assert!(!fs_read.requires_user_consent());
500 assert!(fs_write.requires_user_consent());
501 assert!(sys_cmd.requires_user_consent());
502 }
503
504 #[test]
505 fn test_plugin_categories() {
506 let categories = vec![
507 PluginCategory::Algorithm,
508 PluginCategory::Transformer,
509 PluginCategory::DataProcessor,
510 PluginCategory::Evaluator,
511 PluginCategory::Visualizer,
512 ];
513
514 for category in categories {
515 let mock = testing_utils::MockPlugin::for_category("test", category.clone());
516 assert_eq!(mock.metadata().category, category);
517 }
518 }
519
520 #[test]
521 fn test_type_compatibility() {
522 let mut mock = testing_utils::MockPlugin::new("type_test");
523
524 // Should support f64 by default
525 assert!(mock.is_compatible(TypeId::of::<f64>()));
526
527 // Add i32 support
528 mock.add_supported_type(TypeId::of::<i32>());
529 assert!(mock.is_compatible(TypeId::of::<i32>()));
530
531 // String should not be supported
532 assert!(!mock.is_compatible(TypeId::of::<String>()));
533 }
534
535 #[test]
536 fn test_performance_testing() {
537 let mut tester = PluginPerformanceTester::new();
538 let mut mock = testing_utils::MockPlugin::new("perf_test");
539
540 let result = tester.benchmark_initialization(&mut mock);
541 assert!(result.success);
542 assert_eq!(result.operation, "initialization");
543 }
544
545 #[test]
546 fn test_marketplace_components() {
547 let marketplace = PluginMarketplace::new();
548
549 // Test feature score calculation
550 let score = marketplace.calculate_feature_score(4.5, 1000, 50);
551 assert!(score > 0.0);
552 assert!(score <= 10.0);
553 }
554
555 #[test]
556 fn test_trust_store() {
557 let mut trust_store = TrustStore::new();
558
559 let key_info = PublicKeyInfo {
560 algorithm: "RSA".to_string(),
561 key_size: 2048,
562 added_timestamp: std::time::SystemTime::now(),
563 expires_at: None,
564 owner: "test@example.com".to_string(),
565 };
566
567 trust_store.add_trusted_key("test_key".to_string(), key_info);
568 assert!(!trust_store.is_key_revoked("test_key"));
569
570 trust_store.revoke_key("test_key".to_string());
571 assert!(trust_store.is_key_revoked("test_key"));
572 }
573}
574
575// Module feature gates for optional functionality
576// PluginLoader already exported above unconditionally
577
578// External dependencies documentation
579//
580// # External Dependencies
581//
582// This module uses several external crates for enhanced functionality:
583//
584// - `libloading` - For dynamic library loading (when `dynamic_loading` feature is enabled)
585// - `serde` - For serialization of plugin manifests and configurations
586// - `tokio` - For async functionality in discovery and marketplace features
587//
588// # Feature Flags
589//
590// - `dynamic_loading` - Enables dynamic library loading capabilities
591// - `async` - Enables async functionality for marketplace and discovery
592// - `serde` - Enables serialization support for plugin configurations
593//
594// # Platform Support
595//
596// The plugin system supports the following platforms:
597//
598// - **Linux**: Full support including dynamic loading (.so files)
599// - **macOS**: Full support including dynamic loading (.dylib files)
600// - **Windows**: Full support including dynamic loading (.dll files)
601//
602// # Safety Considerations
603//
604// Dynamic loading involves unsafe operations. The plugin system takes several
605// precautions to ensure safety:
606//
607// - Comprehensive validation before loading
608// - Digital signature verification
609// - Permission-based security model
610// - Sandboxed execution environment
611// - Memory safety checks
612//
613// However, users should only load plugins from trusted sources and always
614// validate plugin manifests before installation.