sklears_core/plugin/factory_builder.rs
1//! Plugin Factory and Configuration Builder
2//!
3//! This module provides factory patterns and builders for creating plugin instances
4//! and configurations. It enables flexible plugin creation with configurable
5//! parameters and runtime settings.
6
7use super::core_traits::Plugin;
8use super::types_config::{LogLevel, PluginConfig, PluginMetadata, PluginParameter};
9use crate::error::Result;
10
11/// Factory for creating plugin instances
12///
13/// The PluginFactory trait provides a standardized interface for creating
14/// plugin instances with specific configurations. This enables dynamic
15/// plugin creation and configuration management.
16///
17/// # Examples
18///
19/// ```rust,no_run
20/// use sklears_core::plugin::{PluginFactory, Plugin, PluginConfig, PluginMetadata};
21/// use sklears_core::error::Result;
22///
23/// struct LinearRegressionFactory;
24///
25/// impl PluginFactory for LinearRegressionFactory {
26/// fn create_plugin(&self, config: &PluginConfig) -> Result<Box<dyn Plugin>> {
27/// // Create and configure the plugin based on the provided config
28/// // Box::new(LinearRegressionPlugin::new(config))
29/// todo!("Implement plugin creation")
30/// }
31///
32/// fn metadata(&self) -> PluginMetadata {
33/// PluginMetadata {
34/// name: "LinearRegression".to_string(),
35/// version: "1.0.0".to_string(),
36/// description: "Linear regression algorithm".to_string(),
37/// ..Default::default()
38/// }
39/// }
40///
41/// fn validate_config(&self, config: &PluginConfig) -> Result<()> {
42/// // Validate configuration parameters
43/// Ok(())
44/// }
45/// }
46/// ```
47pub trait PluginFactory: Send + Sync {
48 /// Create a new plugin instance
49 ///
50 /// This method creates a new plugin instance configured according to
51 /// the provided configuration. The factory should validate the configuration
52 /// and return an error if the plugin cannot be created with the given settings.
53 ///
54 /// # Arguments
55 ///
56 /// * `config` - The configuration for the plugin instance
57 ///
58 /// # Returns
59 ///
60 /// A boxed plugin instance, or an error if creation fails.
61 fn create_plugin(&self, config: &PluginConfig) -> Result<Box<dyn Plugin>>;
62
63 /// Get plugin metadata
64 ///
65 /// Returns metadata describing the plugins that this factory can create.
66 /// This includes information about capabilities, supported types, and
67 /// configuration requirements.
68 ///
69 /// # Returns
70 ///
71 /// Metadata for plugins created by this factory.
72 fn metadata(&self) -> PluginMetadata;
73
74 /// Validate configuration
75 ///
76 /// Validates that the provided configuration is suitable for creating
77 /// a plugin instance. This should check parameter types, ranges, and
78 /// any dependencies or requirements.
79 ///
80 /// # Arguments
81 ///
82 /// * `config` - The configuration to validate
83 ///
84 /// # Returns
85 ///
86 /// Ok(()) if the configuration is valid, or an error describing
87 /// what is invalid.
88 fn validate_config(&self, config: &PluginConfig) -> Result<()>;
89
90 /// Get default configuration
91 ///
92 /// Returns a default configuration that can be used to create a plugin
93 /// instance with sensible defaults. This provides a starting point for
94 /// configuration customization.
95 ///
96 /// # Returns
97 ///
98 /// A default plugin configuration.
99 fn default_config(&self) -> PluginConfig {
100 PluginConfig::default()
101 }
102
103 /// Get configuration schema
104 ///
105 /// Returns information about the configuration parameters that this
106 /// factory accepts, including their types, ranges, and descriptions.
107 /// This can be used for automatic UI generation or documentation.
108 ///
109 /// # Returns
110 ///
111 /// A map of parameter names to their descriptions and constraints.
112 fn config_schema(&self) -> std::collections::HashMap<String, String> {
113 std::collections::HashMap::new()
114 }
115}
116
117/// Builder for creating plugin configurations
118///
119/// The PluginConfigBuilder provides a fluent interface for constructing
120/// plugin configurations with various parameters and runtime settings.
121/// It ensures type safety and provides convenient methods for common
122/// configuration patterns.
123///
124/// # Examples
125///
126/// ```rust
127/// use sklears_core::plugin::{PluginConfigBuilder, PluginParameter, LogLevel};
128///
129/// let config = PluginConfigBuilder::new()
130/// .with_parameter("learning_rate", PluginParameter::Float(0.01))
131/// .with_parameter("max_iterations", PluginParameter::Int(1000))
132/// .with_parameter("use_bias", PluginParameter::Bool(true))
133/// .with_threads(4)
134/// .with_memory_limit(1024 * 1024 * 1024) // 1GB
135/// .with_timeout(30000) // 30 seconds
136/// .with_gpu(true)
137/// .with_log_level(LogLevel::Info)
138/// .with_setting("backend", "cuda")
139/// .build();
140/// ```
141#[derive(Debug, Clone)]
142pub struct PluginConfigBuilder {
143 /// The configuration being built
144 config: PluginConfig,
145}
146
147impl PluginConfigBuilder {
148 /// Create a new config builder
149 ///
150 /// Initializes a new builder with default configuration values.
151 ///
152 /// # Examples
153 ///
154 /// ```rust
155 /// use sklears_core::plugin::PluginConfigBuilder;
156 ///
157 /// let builder = PluginConfigBuilder::new();
158 /// let config = builder.build();
159 /// ```
160 pub fn new() -> Self {
161 Self {
162 config: PluginConfig::default(),
163 }
164 }
165
166 /// Add a parameter to the configuration
167 ///
168 /// Adds a named parameter with the specified value to the configuration.
169 /// This method can be chained to add multiple parameters.
170 ///
171 /// # Arguments
172 ///
173 /// * `key` - The parameter name
174 /// * `value` - The parameter value
175 ///
176 /// # Examples
177 ///
178 /// ```rust
179 /// use sklears_core::plugin::{PluginConfigBuilder, PluginParameter};
180 ///
181 /// let config = PluginConfigBuilder::new()
182 /// .with_parameter("learning_rate", PluginParameter::Float(0.01))
183 /// .with_parameter("regularization", PluginParameter::Float(0.001))
184 /// .build();
185 /// ```
186 pub fn with_parameter(mut self, key: &str, value: PluginParameter) -> Self {
187 self.config.parameters.insert(key.to_string(), value);
188 self
189 }
190
191 /// Add multiple parameters at once
192 ///
193 /// Convenience method for adding multiple parameters from a map.
194 ///
195 /// # Arguments
196 ///
197 /// * `params` - Map of parameter names to values
198 pub fn with_parameters(
199 mut self,
200 params: std::collections::HashMap<String, PluginParameter>,
201 ) -> Self {
202 self.config.parameters.extend(params);
203 self
204 }
205
206 /// Set the number of threads to use
207 ///
208 /// Configures the number of threads that the plugin should use for
209 /// parallel processing. If not set, the plugin will use its default
210 /// threading behavior.
211 ///
212 /// # Arguments
213 ///
214 /// * `threads` - Number of threads to use
215 ///
216 /// # Examples
217 ///
218 /// ```rust
219 /// use sklears_core::plugin::PluginConfigBuilder;
220 ///
221 /// let config = PluginConfigBuilder::new()
222 /// .with_threads(8)
223 /// .build();
224 /// ```
225 pub fn with_threads(mut self, threads: usize) -> Self {
226 self.config.runtime_settings.num_threads = Some(threads);
227 self
228 }
229
230 /// Set memory limit in bytes
231 ///
232 /// Configures the maximum amount of memory that the plugin should use.
233 /// This can help prevent out-of-memory errors in resource-constrained
234 /// environments.
235 ///
236 /// # Arguments
237 ///
238 /// * `limit` - Memory limit in bytes
239 ///
240 /// # Examples
241 ///
242 /// ```rust
243 /// use sklears_core::plugin::PluginConfigBuilder;
244 ///
245 /// let config = PluginConfigBuilder::new()
246 /// .with_memory_limit(2 * 1024 * 1024 * 1024) // 2GB
247 /// .build();
248 /// ```
249 pub fn with_memory_limit(mut self, limit: usize) -> Self {
250 self.config.runtime_settings.memory_limit = Some(limit);
251 self
252 }
253
254 /// Set timeout in milliseconds
255 ///
256 /// Configures the maximum time that plugin operations should take
257 /// before timing out. This can help prevent hanging operations.
258 ///
259 /// # Arguments
260 ///
261 /// * `timeout_ms` - Timeout in milliseconds
262 ///
263 /// # Examples
264 ///
265 /// ```rust
266 /// use sklears_core::plugin::PluginConfigBuilder;
267 ///
268 /// let config = PluginConfigBuilder::new()
269 /// .with_timeout(60000) // 1 minute
270 /// .build();
271 /// ```
272 pub fn with_timeout(mut self, timeout_ms: u64) -> Self {
273 self.config.runtime_settings.timeout_ms = Some(timeout_ms);
274 self
275 }
276
277 /// Enable or disable GPU acceleration
278 ///
279 /// Configures whether the plugin should use GPU acceleration if available.
280 ///
281 /// # Arguments
282 ///
283 /// * `use_gpu` - Whether to use GPU acceleration
284 ///
285 /// # Examples
286 ///
287 /// ```rust
288 /// use sklears_core::plugin::PluginConfigBuilder;
289 ///
290 /// let config = PluginConfigBuilder::new()
291 /// .with_gpu(true)
292 /// .build();
293 /// ```
294 pub fn with_gpu(mut self, use_gpu: bool) -> Self {
295 self.config.runtime_settings.use_gpu = use_gpu;
296 self
297 }
298
299 /// Set logging level
300 ///
301 /// Configures the verbosity of logging output from the plugin.
302 ///
303 /// # Arguments
304 ///
305 /// * `level` - The logging level to use
306 ///
307 /// # Examples
308 ///
309 /// ```rust
310 /// use sklears_core::plugin::{PluginConfigBuilder, LogLevel};
311 ///
312 /// let config = PluginConfigBuilder::new()
313 /// .with_log_level(LogLevel::Debug)
314 /// .build();
315 /// ```
316 pub fn with_log_level(mut self, level: LogLevel) -> Self {
317 self.config.runtime_settings.log_level = level;
318 self
319 }
320
321 /// Add a plugin-specific setting
322 ///
323 /// Adds a custom setting that is specific to the plugin being configured.
324 /// These settings are typically used for plugin-specific configuration
325 /// that doesn't fit into the standard parameter system.
326 ///
327 /// # Arguments
328 ///
329 /// * `key` - The setting name
330 /// * `value` - The setting value
331 ///
332 /// # Examples
333 ///
334 /// ```rust
335 /// use sklears_core::plugin::PluginConfigBuilder;
336 ///
337 /// let config = PluginConfigBuilder::new()
338 /// .with_setting("backend", "tensorflow")
339 /// .with_setting("device", "/gpu:0")
340 /// .build();
341 /// ```
342 pub fn with_setting(mut self, key: &str, value: &str) -> Self {
343 self.config
344 .plugin_settings
345 .insert(key.to_string(), value.to_string());
346 self
347 }
348
349 /// Add multiple settings at once
350 ///
351 /// Convenience method for adding multiple plugin-specific settings.
352 ///
353 /// # Arguments
354 ///
355 /// * `settings` - Map of setting names to values
356 pub fn with_settings(mut self, settings: std::collections::HashMap<String, String>) -> Self {
357 self.config.plugin_settings.extend(settings);
358 self
359 }
360
361 /// Build the final configuration
362 ///
363 /// Consumes the builder and returns the constructed configuration.
364 ///
365 /// # Returns
366 ///
367 /// The configured PluginConfig instance.
368 ///
369 /// # Examples
370 ///
371 /// ```rust
372 /// use sklears_core::plugin::{PluginConfigBuilder, PluginParameter};
373 ///
374 /// let config = PluginConfigBuilder::new()
375 /// .with_parameter("learning_rate", PluginParameter::Float(0.01))
376 /// .with_threads(4)
377 /// .build();
378 /// ```
379 pub fn build(self) -> PluginConfig {
380 self.config
381 }
382
383 /// Get a reference to the current configuration
384 ///
385 /// Returns a reference to the configuration being built without
386 /// consuming the builder. This can be useful for inspecting the
387 /// current state during construction.
388 ///
389 /// # Returns
390 ///
391 /// A reference to the current configuration.
392 pub fn config(&self) -> &PluginConfig {
393 &self.config
394 }
395
396 /// Validate the current configuration
397 ///
398 /// Validates the current configuration state without building it.
399 /// This can be useful for checking configuration validity during
400 /// the building process.
401 ///
402 /// # Returns
403 ///
404 /// Ok(()) if the configuration is valid, or an error describing
405 /// what is invalid.
406 pub fn validate(&self) -> Result<()> {
407 // Basic validation - can be extended
408 if self.config.runtime_settings.num_threads == Some(0) {
409 return Err(crate::error::SklearsError::InvalidOperation(
410 "Number of threads cannot be zero".to_string(),
411 ));
412 }
413
414 if let Some(timeout) = self.config.runtime_settings.timeout_ms {
415 if timeout == 0 {
416 return Err(crate::error::SklearsError::InvalidOperation(
417 "Timeout cannot be zero".to_string(),
418 ));
419 }
420 }
421
422 Ok(())
423 }
424
425 /// Clone the builder
426 ///
427 /// Creates a copy of the current builder state, allowing for
428 /// branching configuration construction.
429 ///
430 /// # Returns
431 ///
432 /// A cloned builder with the same configuration state.
433 pub fn clone_builder(&self) -> Self {
434 self.clone()
435 }
436}
437
438impl Default for PluginConfigBuilder {
439 fn default() -> Self {
440 Self::new()
441 }
442}
443
444/// Convenience functions for common plugin configurations
445impl PluginConfigBuilder {
446 /// Create a configuration optimized for CPU-intensive tasks
447 ///
448 /// Sets up a configuration with appropriate threading and resource
449 /// settings for CPU-bound algorithms.
450 pub fn cpu_optimized() -> Self {
451 Self::new()
452 .with_threads(num_cpus::get())
453 .with_gpu(false)
454 .with_log_level(LogLevel::Info)
455 }
456
457 /// Create a configuration optimized for GPU acceleration
458 ///
459 /// Sets up a configuration with GPU acceleration enabled and
460 /// appropriate resource settings.
461 pub fn gpu_optimized() -> Self {
462 Self::new()
463 .with_gpu(true)
464 .with_threads(2) // Fewer CPU threads when using GPU
465 .with_log_level(LogLevel::Info)
466 }
467
468 /// Create a configuration for development/debugging
469 ///
470 /// Sets up a configuration with verbose logging and longer timeouts
471 /// suitable for development environments.
472 pub fn development() -> Self {
473 Self::new()
474 .with_log_level(LogLevel::Debug)
475 .with_timeout(300000) // 5 minutes
476 .with_threads(1) // Single-threaded for easier debugging
477 }
478
479 /// Create a configuration for production environments
480 ///
481 /// Sets up a configuration with optimized settings for production use,
482 /// including appropriate resource limits and logging levels.
483 pub fn production() -> Self {
484 Self::new()
485 .with_log_level(LogLevel::Warn)
486 .with_timeout(30000) // 30 seconds
487 .with_memory_limit(4 * 1024 * 1024 * 1024) // 4GB
488 .with_threads(num_cpus::get())
489 }
490}