plux_rs/
loader.rs

1use rayon::prelude::{
2    IndexedParallelIterator, IntoParallelIterator, IntoParallelRefIterator,
3    IntoParallelRefMutIterator, ParallelIterator,
4};
5use semver::Version;
6
7use crate::{
8    Bundle, Info, LoaderContext, Manager, Plugin, PluginInfo, Registry, Requests,
9    utils::{
10        LoadPluginError, PluginCallRequestError, Ptr, RegisterManagerError, RegisterPluginError,
11        StopLoaderError, UnloadPluginError, UnregisterManagerError, UnregisterPluginError,
12    },
13    variable::Variable,
14};
15
16/// Main loader for plugins and managers.
17///
18/// The Loader is the central component of Plux responsible for managing the entire plugin ecosystem.
19/// It handles plugin discovery, loading, unloading, and provides the interface for interacting
20/// with plugins and managers.
21///
22/// # Type Parameters
23///
24/// * `'a` - Lifetime parameter for references within the loader
25/// * `O` - Output type for plugin functions (must implement Send + Sync)
26/// * `I` - Plugin information type (must implement Info trait)
27///
28/// # Fields
29///
30/// * `managers` - Collection of registered plugin managers
31/// * `registry` - Registry of functions available to plugins
32/// * `requests` - Collection of function requests from the host for plugins
33/// * `plugins` - Collection of loaded plugins
34///
35/// # Example
36///
37/// ```rust,no_run,ignore
38/// use plux_rs::prelude::*;
39/// use plux_custom_manager::CustomManager;
40///
41/// let mut loader = Loader::new();
42/// loader.context(|mut ctx| {
43///     ctx.register_manager(CustomManager::new())?;
44///     // Register functions and requests here
45///     Ok(())
46/// });
47/// ```
48//TODO: Conduct a small code refactoring for comfortable use of the library by Rust programmers
49pub struct Loader<'a, O: Send + Sync, I: Info> {
50    pub(crate) managers: Vec<Box<dyn Manager<'a, O, I>>>,
51    pub(crate) registry: Registry<O>,
52    pub(crate) requests: Requests,
53    pub(crate) plugins: Vec<Plugin<'a, O, I>>,
54}
55
56impl<'a, O: Send + Sync, I: Info> Loader<'a, O, I> {
57    /// Creates a new plugin loader instance.
58    ///
59    /// Initializes an empty loader with no managers, plugins, or functions registered.
60    ///
61    /// # Returns
62    ///
63    /// Returns a new Loader instance ready for configuration.
64    pub const fn new() -> Self {
65        Self {
66            managers: vec![],
67            registry: vec![],
68            requests: vec![],
69            plugins: vec![],
70        }
71    }
72
73    /// Provides access to the loader context for configuration.
74    ///
75    /// This method creates a context that allows registering managers, functions, and requests
76    /// with the loader. The context ensures proper initialization order and provides a fluent
77    /// interface for loader setup.
78    ///
79    /// # Parameters
80    ///
81    /// * `f` - Closure that receives the loader context and returns a result
82    ///
83    /// # Returns
84    ///
85    /// Returns the result of the closure execution.
86    ///
87    /// # Example
88    ///
89    /// ```rust,no_run
90    /// use plux_rs::{Loader, StdInfo};
91    ///
92    /// let mut loader = Loader::<'_, (), StdInfo>::new();
93    /// loader.context(|mut ctx| {
94    ///     // Register managers, functions, and requests here
95    ///     Ok::<(), Box<dyn std::error::Error>>(())
96    /// });
97    /// ```
98    pub fn context<FO, R>(&mut self, f: FO) -> R
99    where
100        FO: FnOnce(LoaderContext<'a, '_, O, I>) -> R,
101    {
102        f(LoaderContext::new(self))
103    }
104
105    /// Stops the loader and cleans up all resources.
106    ///
107    /// This method unloads all plugins and unregisters all managers in the correct order,
108    /// ensuring proper cleanup of resources.
109    ///
110    /// # Returns
111    ///
112    /// Returns `Result<(), StopLoaderError>` indicating success or failure of the shutdown process.
113    pub fn stop(&mut self) -> Result<(), StopLoaderError> {
114        private_loader::stop_plugins(self)?;
115        private_loader::stop_managers(self)?;
116        Ok(())
117    }
118
119    /// Registers a plugin manager with the loader.
120    ///
121    /// This method registers a manager that can handle plugins of a specific format.
122    /// The manager will be used to load and manage plugins matching its format.
123    ///
124    /// # Parameters
125    ///
126    /// * `manager` - The manager instance to register
127    ///
128    /// # Returns
129    ///
130    /// Returns `Result<(), RegisterManagerError>` indicating success or failure.
131    /// Fails if a manager with the same format is already registered.
132    ///
133    /// # Type Parameters
134    ///
135    /// * `M` - Type of the manager (must implement Manager trait)
136    pub fn register_manager<M>(&mut self, manager: M) -> Result<(), RegisterManagerError>
137    where
138        M: Manager<'a, O, I> + 'static,
139    {
140        private_loader::register_manager(self, Box::new(manager))
141    }
142
143    /// Forcefully registers a plugin manager, bypassing safety checks.
144    ///
145    /// This unsafe method allows registering a manager without checking for format conflicts.
146    /// Use with caution as it may lead to undefined behavior.
147    ///
148    /// # Parameters
149    ///
150    /// * `manager` - The manager instance to register
151    ///
152    /// # Returns
153    ///
154    /// Returns `Result<(), RegisterManagerError>` indicating success or failure.
155    ///
156    /// # Safety
157    ///
158    /// This method is unsafe because it bypasses format conflict checks that prevent
159    /// multiple managers from handling the same plugin format.
160    pub unsafe fn forced_register_manager(
161        &mut self,
162        manager: Box<dyn Manager<'a, O, I>>,
163    ) -> Result<(), RegisterManagerError> {
164        private_loader::forced_register_manager(self, manager)
165    }
166
167    /// Registers multiple plugin managers with the loader.
168    ///
169    /// This method registers a collection of managers in sequence.
170    /// Stops at the first error encountered.
171    ///
172    /// # Parameters
173    ///
174    /// * `managers` - Iterator of manager instances to register
175    ///
176    /// # Returns
177    ///
178    /// Returns `Result<(), RegisterManagerError>` indicating success or failure.
179    pub fn register_managers<M>(&mut self, managers: M) -> Result<(), RegisterManagerError>
180    where
181        M: IntoIterator<Item = Box<dyn Manager<'a, O, I>>>,
182    {
183        managers
184            .into_iter()
185            .try_for_each(|manager| private_loader::register_manager(self, manager))?;
186
187        Ok(())
188    }
189
190    /// Registers multiple plugin managers in parallel.
191    ///
192    /// This method registers a collection of managers concurrently using parallel processing.
193    /// More efficient for large numbers of managers.
194    ///
195    /// # Parameters
196    ///
197    /// * `managers` - Parallel iterator of manager instances to register
198    ///
199    /// # Returns
200    ///
201    /// Returns `Result<(), RegisterManagerError>` indicating success or failure.
202    pub fn par_register_managers<M>(&mut self, managers: M) -> Result<(), RegisterManagerError>
203    where
204        M: IntoParallelIterator<Item = Box<dyn Manager<'a, O, I>>>,
205    {
206        let this = Ptr::new(self);
207        managers.into_par_iter().try_for_each(move |manager| {
208            private_loader::register_manager(this.as_mut(), manager)
209        })?;
210
211        Ok(())
212    }
213
214    /// Unregisters a plugin manager from the loader.
215    ///
216    /// This method removes a manager from the loader, first unloading any plugins
217    /// associated with that manager.
218    ///
219    /// # Parameters
220    ///
221    /// * `format` - The format of the manager to unregister
222    ///
223    /// # Returns
224    ///
225    /// Returns `Result<(), UnregisterManagerError>` indicating success or failure.
226    pub fn unregister_manager(&mut self, format: &str) -> Result<(), UnregisterManagerError> {
227        let index = self
228            .managers
229            .iter()
230            .enumerate()
231            .find_map(|(i, manager)| match manager.format() == format {
232                true => Some(i),
233                false => None,
234            })
235            .ok_or(UnregisterManagerError::NotFound)?;
236
237        private_loader::unregister_manager(self, index)
238    }
239
240    /// Forcefully unregisters a plugin manager, bypassing safety checks.
241    ///
242    /// This unsafe method allows unregistering a manager without checking if it exists.
243    /// Use with caution as it may lead to undefined behavior.
244    ///
245    /// # Parameters
246    ///
247    /// * `index` - Index of the manager to unregister
248    ///
249    /// # Returns
250    ///
251    /// Returns `Result<(), UnregisterManagerError>` indicating success or failure.
252    ///
253    /// # Safety
254    ///
255    /// This method is unsafe because it bypasses existence checks that prevent
256    /// accessing invalid memory or indices.
257    pub unsafe fn forced_unregister_manager(
258        &mut self,
259        index: usize,
260    ) -> Result<(), UnregisterManagerError> {
261        private_loader::forced_unregister_manager(&mut self.managers, index)
262    }
263
264    /*
265    TODO: Refactoring example: Add manager search by its type
266    *     Example: let manager = loader.get_manager::<MyManager>();
267    */
268    /// Gets an immutable reference to a manager by format.
269    ///
270    /// Searches for a registered manager that handles the specified format.
271    ///
272    /// # Parameters
273    ///
274    /// * `format` - The plugin format to search for (e.g., "lua", "rs")
275    ///
276    /// # Returns
277    ///
278    /// Returns `Option<&Box<dyn Manager<'a, O, I>>>` containing the manager if found.
279    pub fn get_manager_ref(&self, format: &str) -> Option<&Box<dyn Manager<'a, O, I>>> {
280        self.managers.iter().find(|m| m.format() == format)
281    }
282
283    /// Gets an immutable reference to a manager by format (parallel version).
284    ///
285    /// Searches for a registered manager that handles the specified format using parallel processing.
286    ///
287    /// # Parameters
288    ///
289    /// * `format` - The plugin format to search for (e.g., "lua", "rs")
290    ///
291    /// # Returns
292    ///
293    /// Returns `Option<&Box<dyn Manager<'a, O, I>>>` containing the manager if found.
294    pub fn par_get_manager_ref(&self, format: &str) -> Option<&Box<dyn Manager<'a, O, I>>> {
295        self.managers
296            .par_iter()
297            .find_first(|m| m.format() == format)
298    }
299
300    /// Gets a mutable reference to a manager by format.
301    ///
302    /// Searches for a registered manager that handles the specified format.
303    ///
304    /// # Parameters
305    ///
306    /// * `format` - The plugin format to search for (e.g., "lua", "rs")
307    ///
308    /// # Returns
309    ///
310    /// Returns `Option<&mut Box<dyn Manager<'a, O, I>>>` containing the manager if found.
311    pub fn get_manager_mut(&mut self, format: &str) -> Option<&mut Box<dyn Manager<'a, O, I>>> {
312        self.managers.iter_mut().find(|m| m.format() == format)
313    }
314
315    /// Gets a mutable reference to a manager by format (parallel version).
316    ///
317    /// Searches for a registered manager that handles the specified format using parallel processing.
318    ///
319    /// # Parameters
320    ///
321    /// * `format` - The plugin format to search for (e.g., "lua", "rs")
322    ///
323    /// # Returns
324    ///
325    /// Returns `Option<&mut Box<dyn Manager<'a, O, I>>>` containing the manager if found.
326    pub fn par_get_manager_mut(&mut self, format: &str) -> Option<&mut Box<dyn Manager<'a, O, I>>> {
327        self.managers
328            .par_iter_mut()
329            .find_first(|m| m.format() == format)
330    }
331
332    //TODO: Add parallel version
333    /// Registers a plugin with the loader.
334    ///
335    /// This method registers a plugin from the specified path, using the appropriate
336    /// manager based on the plugin's format.
337    ///
338    /// # Parameters
339    ///
340    /// * `path` - Path to the plugin file or directory
341    ///
342    /// # Returns
343    ///
344    /// Returns `Result<Bundle, RegisterPluginError>` containing the plugin bundle on success.
345    pub fn register_plugin(&mut self, path: &str) -> Result<Bundle, RegisterPluginError> {
346        private_loader::register_plugin(self, path)
347    }
348
349    /// Forcefully registers a plugin, bypassing safety checks.
350    ///
351    /// This unsafe method allows registering a plugin without checking for duplicates.
352    /// Use with caution as it may lead to undefined behavior.
353    ///
354    /// # Parameters
355    ///
356    /// * `manager` - Reference to the manager that will handle this plugin
357    /// * `plugin_info` - Plugin information to register
358    ///
359    /// # Returns
360    ///
361    /// Returns `Result<Bundle, RegisterPluginError>` containing the plugin bundle on success.
362    ///
363    /// # Safety
364    ///
365    /// This method is unsafe because it bypasses duplicate checking that prevents
366    /// multiple plugins with the same ID and version from being registered.
367    pub unsafe fn forced_register_plugin(
368        &mut self,
369        manager: &mut Box<dyn Manager<'a, O, I>>,
370        plugin_info: PluginInfo<I>,
371    ) -> Result<Bundle, RegisterPluginError> {
372        private_loader::forced_register_plugin(&mut self.plugins, Ptr::new(manager), plugin_info)
373    }
374
375    /// Registers multiple plugins with the loader.
376    ///
377    /// This method registers multiple plugins from the specified paths in sequence.
378    ///
379    /// # Parameters
380    ///
381    /// * `paths` - Iterator of paths to plugin files or directories
382    ///
383    /// # Returns
384    ///
385    /// Returns `Result<Vec<Bundle>, RegisterPluginError>` containing the plugin bundles on success.
386    ///
387    /// # Type Parameters
388    ///
389    /// * `'b` - Lifetime of the path references
390    /// * `P` - Type of the iterator containing path references
391    pub fn register_plugins<'b, P>(&mut self, paths: P) -> Result<Vec<Bundle>, RegisterPluginError>
392    where
393        P: IntoIterator<Item = &'b str>,
394    {
395        paths
396            .into_iter()
397            .map(|path| private_loader::register_plugin(self, path))
398            .collect::<Result<Vec<_>, _>>()
399    }
400
401    /// Registers multiple plugins with the loader in parallel.
402    ///
403    /// This method registers multiple plugins from the specified paths concurrently.
404    ///
405    /// # Parameters
406    ///
407    /// * `paths` - Parallel iterator of paths to plugin files or directories
408    ///
409    /// # Returns
410    ///
411    /// Returns `Result<Vec<Bundle>, RegisterPluginError>` containing the plugin bundles on success.
412    ///
413    /// # Type Parameters
414    ///
415    /// * `'b` - Lifetime of the path references
416    /// * `P` - Type of the parallel iterator containing path references
417    pub fn par_register_plugins<'b, P>(
418        &mut self,
419        paths: P,
420    ) -> Result<Vec<Bundle>, RegisterPluginError>
421    where
422        P: IntoParallelIterator<Item = &'b str>,
423    {
424        let this = Ptr::new(self);
425
426        paths
427            .into_par_iter()
428            .map(move |path| private_loader::register_plugin(this.as_mut(), path))
429            .collect::<Result<Vec<_>, _>>()
430    }
431
432    /// Unregisters a plugin from the loader.
433    ///
434    /// This method removes a plugin from the loader by ID and version, first unloading it if necessary.
435    ///
436    /// # Parameters
437    ///
438    /// * `id` - Plugin identifier
439    /// * `version` - Plugin version
440    ///
441    /// # Returns
442    ///
443    /// Returns `Result<(), UnregisterPluginError>` indicating success or failure.
444    pub fn unregister_plugin(
445        &mut self,
446        id: &str,
447        version: &Version,
448    ) -> Result<(), UnregisterPluginError> {
449        let index = self
450            .plugins
451            .iter()
452            .position(|plugin| *plugin == (id, version))
453            .ok_or(UnregisterPluginError::NotFound)?;
454        private_loader::unregister_plugin(&mut self.plugins, index)
455    }
456
457    /// Unregisters a plugin from the loader by bundle.
458    ///
459    /// This method removes a plugin from the loader by bundle information, first unloading it if necessary.
460    ///
461    /// # Parameters
462    ///
463    /// * `bundle` - Plugin bundle information
464    ///
465    /// # Returns
466    ///
467    /// Returns `Result<(), UnregisterPluginError>` indicating success or failure.
468    pub fn unregister_plugin_by_bundle(
469        &mut self,
470        bundle: &Bundle,
471    ) -> Result<(), UnregisterPluginError> {
472        let index = self
473            .plugins
474            .iter()
475            .position(|plugin| *plugin == *bundle)
476            .ok_or(UnregisterPluginError::NotFound)?;
477        private_loader::unregister_plugin(&mut self.plugins, index)
478    }
479
480    /// Unregisters a plugin from the loader by bundle (parallel version).
481    ///
482    /// This method removes a plugin from the loader by bundle information using parallel processing,
483    /// first unloading it if necessary.
484    ///
485    /// # Parameters
486    ///
487    /// * `bundle` - Plugin bundle information
488    ///
489    /// # Returns
490    ///
491    /// Returns `Result<(), UnregisterPluginError>` indicating success or failure.
492    pub fn par_unregister_plugin_by_bundle(
493        &mut self,
494        bundle: &Bundle,
495    ) -> Result<(), UnregisterPluginError> {
496        let index = self
497            .plugins
498            .par_iter()
499            .position_first(|plugin| *plugin == *bundle)
500            .ok_or(UnregisterPluginError::NotFound)?;
501        private_loader::unregister_plugin(&mut self.plugins, index)
502    }
503
504    /// Forcefully unregisters a plugin, bypassing safety checks.
505    ///
506    /// This unsafe method allows unregistering a plugin without checking if it exists.
507    /// Use with caution as it may lead to undefined behavior.
508    ///
509    /// # Parameters
510    ///
511    /// * `index` - Index of the plugin to unregister
512    ///
513    /// # Returns
514    ///
515    /// Returns `Result<(), UnregisterPluginError>` indicating success or failure.
516    ///
517    /// # Safety
518    ///
519    /// This method is unsafe because it bypasses existence checks that prevent
520    /// accessing invalid memory or indices.
521    pub unsafe fn forced_unregister_plugin(
522        &mut self,
523        index: usize,
524    ) -> Result<(), UnregisterPluginError> {
525        private_loader::forced_unregister_plugin(&mut self.plugins, index)
526    }
527
528    /// Unloads a plugin from the execution environment.
529    ///
530    /// This method unloads a plugin by ID and version, making it unavailable for execution.
531    ///
532    /// # Parameters
533    ///
534    /// * `id` - Plugin identifier
535    /// * `version` - Plugin version
536    ///
537    /// # Returns
538    ///
539    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
540    pub fn unload_plugin(&mut self, id: &str, version: &Version) -> Result<(), UnloadPluginError> {
541        let index = self
542            .plugins
543            .iter()
544            .position(|plugin| *plugin == (id, version))
545            .ok_or(UnloadPluginError::NotFound)?;
546        private_loader::unload_plugin(&mut self.plugins, index)
547    }
548
549    /// Unloads a plugin from the execution environment (parallel version).
550    ///
551    /// This method unloads a plugin by ID and version using parallel processing.
552    ///
553    /// # Parameters
554    ///
555    /// * `id` - Plugin identifier
556    /// * `version` - Plugin version
557    ///
558    /// # Returns
559    ///
560    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
561    pub fn par_unload_plugin(
562        &mut self,
563        id: &str,
564        version: &Version,
565    ) -> Result<(), UnloadPluginError> {
566        let index = self
567            .plugins
568            .par_iter()
569            .position_first(|plugin| *plugin == (id, version))
570            .ok_or(UnloadPluginError::NotFound)?;
571        private_loader::unload_plugin(&mut self.plugins, index)
572    }
573
574    /// Unloads a plugin from the execution environment by bundle.
575    ///
576    /// This method unloads a plugin by bundle information, making it unavailable for execution.
577    ///
578    /// # Parameters
579    ///
580    /// * `bundle` - Plugin bundle information
581    ///
582    /// # Returns
583    ///
584    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
585    pub fn unload_plugin_by_bundle(&mut self, bundle: &Bundle) -> Result<(), UnloadPluginError> {
586        let index = self
587            .plugins
588            .iter()
589            .position(|plugin| *plugin == *bundle)
590            .ok_or(UnloadPluginError::NotFound)?;
591        private_loader::unload_plugin(&mut self.plugins, index)
592    }
593
594    /// Unloads a plugin from the execution environment by bundle (parallel version).
595    ///
596    /// This method unloads a plugin by bundle information using parallel processing.
597    ///
598    /// # Parameters
599    ///
600    /// * `bundle` - Plugin bundle information
601    ///
602    /// # Returns
603    ///
604    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
605    pub fn par_unload_plugin_by_bundle(
606        &mut self,
607        bundle: &Bundle,
608    ) -> Result<(), UnloadPluginError> {
609        let index = self
610            .plugins
611            .par_iter()
612            .position_first(|plugin| *plugin == *bundle)
613            .ok_or(UnloadPluginError::NotFound)?;
614        private_loader::unload_plugin(&mut self.plugins, index)
615    }
616
617    /// Forcefully unloads a plugin, bypassing safety checks.
618    ///
619    /// This unsafe method allows unloading a plugin without checking if it exists.
620    /// Use with caution as it may lead to undefined behavior.
621    ///
622    /// # Parameters
623    ///
624    /// * `index` - Index of the plugin to unload
625    ///
626    /// # Returns
627    ///
628    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
629    ///
630    /// # Safety
631    ///
632    /// This method is unsafe because it bypasses existence checks that prevent
633    /// accessing invalid memory or indices.
634    pub unsafe fn forced_unload_plugin(&mut self, index: usize) -> Result<(), UnloadPluginError> {
635        private_loader::forced_unload_plugin(&mut self.plugins, index)
636    }
637
638    /// Gets an immutable reference to a plugin by ID and version.
639    ///
640    /// Searches for a registered plugin matching the specified ID and version.
641    ///
642    /// # Parameters
643    ///
644    /// * `id` - Plugin identifier
645    /// * `version` - Plugin version
646    ///
647    /// # Returns
648    ///
649    /// Returns `Option<&Plugin<'a, O, I>>` containing the plugin if found.
650    pub fn get_plugin(&self, id: &str, version: &Version) -> Option<&Plugin<'a, O, I>> {
651        self.plugins.iter().find(|plugin| **plugin == (id, version))
652    }
653
654    /// Gets an immutable reference to a plugin by ID and version (parallel version).
655    ///
656    /// Searches for a registered plugin matching the specified ID and version using parallel processing.
657    ///
658    /// # Parameters
659    ///
660    /// * `id` - Plugin identifier
661    /// * `version` - Plugin version
662    ///
663    /// # Returns
664    ///
665    /// Returns `Option<&Plugin<'a, O, I>>` containing the plugin if found.
666    pub fn par_get_plugin(&self, id: &str, version: &Version) -> Option<&Plugin<'a, O, I>> {
667        self.plugins
668            .par_iter()
669            .find_first(|plugin| **plugin == (id, version))
670    }
671
672    /// Gets an immutable reference to a plugin by bundle.
673    ///
674    /// Searches for a registered plugin matching the specified bundle.
675    ///
676    /// # Parameters
677    ///
678    /// * `bundle` - Plugin bundle containing ID, version, and format
679    ///
680    /// # Returns
681    ///
682    /// Returns `Option<&Plugin<'a, O, I>>` containing the plugin if found.
683    pub fn get_plugin_by_bundle(&self, bundle: &Bundle) -> Option<&Plugin<'a, O, I>> {
684        self.plugins.iter().find(|plugin| *plugin == bundle)
685    }
686
687    /// Gets an immutable reference to a plugin by bundle (parallel version).
688    ///
689    /// Searches for a registered plugin matching the specified bundle using parallel processing.
690    ///
691    /// # Parameters
692    ///
693    /// * `bundle` - Plugin bundle containing ID, version, and format
694    ///
695    /// # Returns
696    ///
697    /// Returns `Option<&Plugin<'a, O, I>>` containing the plugin if found.
698    pub fn par_get_plugin_by_bundle(&self, bundle: &Bundle) -> Option<&Plugin<'a, O, I>> {
699        self.plugins
700            .par_iter()
701            .find_first(|plugin| *plugin == bundle)
702    }
703
704    /// Gets a mutable reference to a plugin by ID and version.
705    ///
706    /// This method searches for a registered plugin matching the specified ID and version.
707    ///
708    /// # Parameters
709    ///
710    /// * `id` - Plugin identifier
711    /// * `version` - Plugin version
712    ///
713    /// # Returns
714    ///
715    /// Returns `Option<&mut Plugin<'a, O, I>>` containing the plugin if found.
716    pub fn get_plugin_mut(&mut self, id: &str, version: &Version) -> Option<&mut Plugin<'a, O, I>> {
717        self.plugins
718            .iter_mut()
719            .find(|plugin| **plugin == (id, version))
720    }
721
722    /// Gets a mutable reference to a plugin by ID and version (parallel version).
723    ///
724    /// This method searches for a registered plugin matching the specified ID and version
725    /// using parallel processing.
726    ///
727    /// # Parameters
728    ///
729    /// * `id` - Plugin identifier
730    /// * `version` - Plugin version
731    ///
732    /// # Returns
733    ///
734    /// Returns `Option<&mut Plugin<'a, O, I>>` containing the plugin if found.
735    pub fn par_get_plugin_mut(
736        &mut self,
737        id: &str,
738        version: &Version,
739    ) -> Option<&mut Plugin<'a, O, I>> {
740        self.plugins
741            .par_iter_mut()
742            .find_first(|plugin| **plugin == (id, version))
743    }
744
745    /// Gets a mutable reference to a plugin by bundle.
746    ///
747    /// This method searches for a registered plugin matching the specified bundle.
748    ///
749    /// # Parameters
750    ///
751    /// * `bundle` - Plugin bundle containing ID, version, and format
752    ///
753    /// # Returns
754    ///
755    /// Returns `Option<&mut Plugin<'a, O, I>>` containing the plugin if found.
756    pub fn get_plugin_mut_by_bundle(&mut self, bundle: &Bundle) -> Option<&mut Plugin<'a, O, I>> {
757        self.plugins.iter_mut().find(|plugin| *plugin == bundle)
758    }
759
760    /// Gets a mutable reference to a plugin by bundle (parallel version).
761    ///
762    /// This method searches for a registered plugin matching the specified bundle
763    /// using parallel processing.
764    ///
765    /// # Parameters
766    ///
767    /// * `bundle` - Plugin bundle containing ID, version, and format
768    ///
769    /// # Returns
770    ///
771    /// Returns `Option<&mut Plugin<'a, O, I>>` containing the plugin if found.
772    pub fn par_get_plugin_mut_by_bundle(
773        &mut self,
774        bundle: &Bundle,
775    ) -> Option<&mut Plugin<'a, O, I>> {
776        self.plugins
777            .par_iter_mut()
778            .find_first(|plugin| *plugin == bundle)
779    }
780
781    /// Gets all plugins with the specified ID.
782    ///
783    /// Returns all versions of plugins matching the given ID.
784    ///
785    /// # Parameters
786    ///
787    /// * `id` - Plugin identifier to search for
788    ///
789    /// # Returns
790    ///
791    /// Returns `Vec<&Plugin<'a, O, I>>` containing all matching plugins.
792    pub fn get_plugins_by_id(&self, id: &str) -> Vec<&Plugin<'a, O, I>> {
793        self.plugins
794            .iter()
795            .filter(|plugin| plugin.info.bundle.id == id)
796            .collect()
797    }
798
799    /// Gets all plugins with the specified ID (parallel version).
800    ///
801    /// Returns all versions of plugins matching the given ID using parallel processing.
802    ///
803    /// # Parameters
804    ///
805    /// * `id` - Plugin identifier to search for
806    ///
807    /// # Returns
808    ///
809    /// Returns `Vec<&Plugin<'a, O, I>>` containing all matching plugins.
810    pub fn par_get_plugins_by_id(&self, id: &str) -> Vec<&Plugin<'a, O, I>> {
811        self.plugins
812            .par_iter()
813            .filter(|plugin| plugin.info.bundle.id == id)
814            .collect()
815    }
816
817    /// Gets mutable references to all plugins with the specified ID.
818    ///
819    /// Returns mutable references to all versions of plugins matching the given ID.
820    ///
821    /// # Parameters
822    ///
823    /// * `id` - Plugin identifier to search for
824    ///
825    /// # Returns
826    ///
827    /// Returns `Vec<&mut Plugin<'a, O, I>>` containing all matching plugins.
828    pub fn get_plugins_by_id_mut(&mut self, id: &str) -> Vec<&mut Plugin<'a, O, I>> {
829        self.plugins
830            .iter_mut()
831            .filter(|plugin| plugin.info.bundle.id == id)
832            .collect()
833    }
834
835    /// Gets mutable references to all plugins with the specified ID (parallel version).
836    ///
837    /// Returns mutable references to all versions of plugins matching the given ID using parallel processing.
838    ///
839    /// # Parameters
840    ///
841    /// * `id` - Plugin identifier to search for
842    ///
843    /// # Returns
844    ///
845    /// Returns `Vec<&mut Plugin<'a, O, I>>` containing all matching plugins.
846    pub fn par_get_plugins_by_id_mut(&mut self, id: &str) -> Vec<&mut Plugin<'a, O, I>> {
847        self.plugins
848            .par_iter_mut()
849            .filter(|plugin| plugin.info.bundle.id == id)
850            .collect()
851    }
852
853    //TODO: Add functions for tracking loading and unloading
854    //      of managers or plugins
855
856    /// Gets a reference to all loaded plugins.
857    ///
858    /// Returns the complete list of plugins currently managed by the loader.
859    ///
860    /// # Returns
861    ///
862    /// Returns `&Vec<Plugin<'a, O, I>>` containing all loaded plugins.
863    pub const fn get_plugins(&self) -> &Vec<Plugin<'a, O, I>> {
864        &self.plugins
865    }
866
867    /// Gets a reference to the function registry.
868    ///
869    /// Returns the registry containing all functions available to plugins.
870    ///
871    /// # Returns
872    ///
873    /// Returns `&Registry<O>` containing the function registry.
874    pub const fn get_registry(&self) -> &Registry<O> {
875        &self.registry
876    }
877
878    /// Gets a reference to the function requests.
879    ///
880    /// Returns a set of queries that plugins implement for the host.
881    ///
882    /// # Returns
883    ///
884    /// Returns `&Requests` containing the function requests.
885    pub const fn get_requests(&self) -> &Requests {
886        &self.requests
887    }
888
889    /// Calls a function request across all eligible plugins.
890    ///
891    /// This method calls the specified function request on all plugins that have the highest
892    /// version for their ID (to avoid calling multiple versions of the same plugin).
893    ///
894    /// # Parameters
895    ///
896    /// * `name` - Name of the function request to call
897    /// * `args` - Arguments to pass to the function
898    ///
899    /// # Returns
900    ///
901    /// Returns `Result<Vec<O>, PluginCallRequestError>` containing results from all
902    /// eligible plugins that have the requested function.
903    pub fn call_request(
904        &self,
905        name: &str,
906        args: &[Variable],
907    ) -> Result<Vec<O>, PluginCallRequestError> {
908        self.plugins
909            .iter()
910            .filter_map(|plugin| {
911                let check_version = self.plugins.iter().find(|pl| {
912                    pl.info.bundle.id == plugin.info.bundle.id
913                        && pl.info.bundle.version > plugin.info.bundle.version
914                });
915
916                match check_version {
917                    Some(_) => None,
918                    None => Some(plugin.call_request(name, args)),
919                }
920            })
921            .collect()
922    }
923
924    /// Calls a function request across all eligible plugins (parallel version).
925    ///
926    /// This method calls the specified function request on all plugins that have the highest
927    /// version for their ID (to avoid calling multiple versions of the same plugin) using parallel processing.
928    ///
929    /// # Parameters
930    ///
931    /// * `name` - Name of the function request to call
932    /// * `args` - Arguments to pass to the function
933    ///
934    /// # Returns
935    ///
936    /// Returns `Result<Vec<O>, PluginCallRequestError>` containing results from all
937    /// eligible plugins that have the requested function.
938    pub fn par_call_request(
939        &self,
940        name: &str,
941        args: &[Variable],
942    ) -> Result<Vec<O>, PluginCallRequestError> {
943        let requests: Vec<_> = self
944            .plugins
945            .iter()
946            .filter_map(|plugin| {
947                let check_version = self.plugins.iter().find(|pl| {
948                    pl.info.bundle.id == plugin.info.bundle.id
949                        && pl.info.bundle.version > plugin.info.bundle.version
950                });
951
952                match check_version {
953                    Some(_) => None,
954                    None => Some(&plugin.requests),
955                }
956            })
957            .collect();
958
959        requests
960            .into_par_iter()
961            .map(|requests| {
962                requests
963                    .par_iter()
964                    .find_map_first(|request| match request.name() == name {
965                        true => Some(request.call(args)),
966                        false => None,
967                    })
968                    .ok_or(PluginCallRequestError::NotFound)
969            })
970            .collect()
971    }
972}
973
974impl<O: Send + Sync + 'static, I: Info + 'static> Loader<'static, O, I> {
975    /// Loads a plugin into the execution environment.
976    ///
977    /// This method loads a plugin by ID and version, making it available for execution.
978    ///
979    /// # Parameters
980    ///
981    /// * `id` - Plugin identifier
982    /// * `version` - Plugin version
983    ///
984    /// # Returns
985    ///
986    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
987    pub fn load_plugin(&mut self, id: &str, version: &Version) -> Result<(), LoadPluginError> {
988        let index = self
989            .plugins
990            .iter()
991            .position(|plugin| *plugin == (id, version))
992            .ok_or(LoadPluginError::NotFound)?;
993        private_loader::load_plugin(self, index)
994    }
995
996    /// Loads a plugin into the execution environment (parallel version).
997    ///
998    /// This method loads a plugin by ID and version using parallel processing.
999    ///
1000    /// # Parameters
1001    ///
1002    /// * `id` - Plugin identifier
1003    /// * `version` - Plugin version
1004    ///
1005    /// # Returns
1006    ///
1007    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
1008    pub fn par_load_plugin(&mut self, id: &str, version: &Version) -> Result<(), LoadPluginError> {
1009        let index = self
1010            .plugins
1011            .par_iter()
1012            .position_first(|plugin| *plugin == (id, version))
1013            .ok_or(LoadPluginError::NotFound)?;
1014        private_loader::load_plugin(self, index)
1015    }
1016
1017    /// Loads a plugin into the execution environment by bundle.
1018    ///
1019    /// This method loads a plugin by bundle information, making it available for execution.
1020    ///
1021    /// # Parameters
1022    ///
1023    /// * `bundle` - Plugin bundle information
1024    ///
1025    /// # Returns
1026    ///
1027    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
1028    pub fn load_plugin_by_bundle(&mut self, bundle: &Bundle) -> Result<(), LoadPluginError> {
1029        let index = self
1030            .plugins
1031            .iter()
1032            .position(|plugin| *plugin == *bundle)
1033            .ok_or(LoadPluginError::NotFound)?;
1034        private_loader::load_plugin(self, index)
1035    }
1036
1037    /// Loads a plugin into the execution environment by bundle (parallel version).
1038    ///
1039    /// This method loads a plugin by bundle information using parallel processing.
1040    ///
1041    /// # Parameters
1042    ///
1043    /// * `bundle` - Plugin bundle information
1044    ///
1045    /// # Returns
1046    ///
1047    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
1048    pub fn par_load_plugin_by_bundle(&mut self, bundle: &Bundle) -> Result<(), LoadPluginError> {
1049        let index = self
1050            .plugins
1051            .par_iter()
1052            .position_first(|plugin| *plugin == *bundle)
1053            .ok_or(LoadPluginError::NotFound)?;
1054        private_loader::load_plugin(self, index)
1055    }
1056
1057    /// Forcefully loads a plugin, bypassing safety checks.
1058    ///
1059    /// This unsafe method allows loading a plugin without checking if it exists.
1060    /// Use with caution as it may lead to undefined behavior.
1061    ///
1062    /// # Parameters
1063    ///
1064    /// * `index` - Index of the plugin to load
1065    /// * `depends` - List of dependencies for this plugin
1066    ///
1067    /// # Returns
1068    ///
1069    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
1070    ///
1071    /// # Safety
1072    ///
1073    /// This method is unsafe because it bypasses existence checks that prevent
1074    /// accessing invalid memory or indices.
1075    pub unsafe fn forced_load_plugin(
1076        &mut self,
1077        index: usize,
1078        depends: Vec<(Bundle, bool)>,
1079    ) -> Result<(), LoadPluginError> {
1080        private_loader::forced_load_plugin(self, index, depends)
1081    }
1082
1083    /// Loads a plugin immediately from the specified path.
1084    ///
1085    /// This convenience method registers and loads a plugin in a single operation.
1086    /// First registers the plugin, then loads it and all its dependencies.
1087    ///
1088    /// # Parameters
1089    ///
1090    /// * `path` - Path to the plugin file or directory
1091    ///
1092    /// # Returns
1093    ///
1094    /// Returns `Result<Bundle, (Option<RegisterPluginError>, Option<LoadPluginError>)>`
1095    /// containing the plugin bundle on success, or errors from registration or loading.
1096    ///
1097    /// # Example
1098    ///
1099    /// ```rust,no_run
1100    /// use plux_rs::{Loader, StdInfo};
1101    ///
1102    /// let mut loader = Loader::<'_, (), StdInfo>::new();
1103    /// // Configure loader with managers...
1104    ///
1105    /// let bundle = match loader.load_plugin_now("my_plugin-v1.0.0.cst")  {
1106    ///     Ok(bundle) => bundle,
1107    ///     Err((Some(e), _)) => return Err(e.into()),
1108    ///     Err((None, Some(e))) => return Err(e.into()),
1109    ///     Err((None, None)) => return Err("Unknown error".into()),
1110    /// };
1111    /// 
1112    /// println!("Loaded plugin: {}", bundle.id);
1113    /// # Ok::<(), Box<dyn std::error::Error>>(())
1114    /// ```
1115    pub fn load_plugin_now(
1116        &mut self,
1117        path: &str,
1118    ) -> Result<Bundle, (Option<RegisterPluginError>, Option<LoadPluginError>)> {
1119        let bundle = private_loader::register_plugin(self, path).map_err(|e| (Some(e), None))?;
1120        self.load_plugin_by_bundle(&bundle)
1121            .map_err(|e| (None, Some(e)))?;
1122        Ok(bundle)
1123    }
1124
1125    /// Loads multiple plugins from the specified paths.
1126    ///
1127    /// This method registers and loads multiple plugins in sequence.
1128    ///
1129    /// # Parameters
1130    ///
1131    /// * `paths` - Iterator of paths to plugin files or directories
1132    ///
1133    /// # Returns
1134    ///
1135    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>`
1136    /// containing the plugin bundles on success, or errors from registration or loading.
1137    ///
1138    /// # Type Parameters
1139    ///
1140    /// * `'b` - Lifetime of the path references
1141    /// * `P` - Type of the iterator containing path references
1142    pub fn load_plugins<'b, P>(
1143        &mut self,
1144        paths: P,
1145    ) -> Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>
1146    where
1147        P: IntoIterator<Item = &'b str>,
1148    {
1149        let bundles = self.register_plugins(paths).map_err(|e| (Some(e), None))?;
1150
1151        // Find plugins that are not dependencies of other plugins
1152        let result: Vec<_> = self
1153            .plugins
1154            .iter()
1155            .enumerate()
1156            .filter_map(|(index, plugin)| {
1157                let find_plugin = self.plugins.iter().find(|pl| {
1158                    pl.info
1159                        .info
1160                        .depends()
1161                        .iter()
1162                        .chain(pl.info.info.optional_depends().iter())
1163                        .any(|d| {
1164                            *d == plugin.info.bundle
1165                                && self
1166                                    .plugins
1167                                    .iter()
1168                                    .find(|p| {
1169                                        d.version.matches(&p.info.bundle.version)
1170                                            && p.info.bundle.version > plugin.info.bundle.version
1171                                    })
1172                                    .is_none()
1173                        })
1174                });
1175
1176                match find_plugin {
1177                    Some(_) => None,
1178                    None => Some(index),
1179                }
1180            })
1181            .collect();
1182
1183        result.into_iter().try_for_each(|index| {
1184            private_loader::load_plugin(self, index).map_err(|e| (None, Some(e)))
1185        })?;
1186
1187        Ok(bundles)
1188    }
1189
1190    /// Loads multiple plugins from the specified paths (parallel version).
1191    ///
1192    /// This method registers and loads multiple plugins concurrently using parallel processing.
1193    ///
1194    /// # Parameters
1195    ///
1196    /// * `paths` - Parallel iterator of paths to plugin files or directories
1197    ///
1198    /// # Returns
1199    ///
1200    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>`
1201    /// containing the plugin bundles on success, or errors from registration or loading.
1202    ///
1203    /// # Type Parameters
1204    ///
1205    /// * `'b` - Lifetime of the path references
1206    /// * `P` - Type of the parallel iterator containing path references
1207    pub fn par_load_plugins<'b, P>(
1208        &mut self,
1209        paths: P,
1210    ) -> Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>
1211    where
1212        P: IntoParallelIterator<Item = &'b str>,
1213    {
1214        let bundles = self
1215            .par_register_plugins(paths)
1216            .map_err(|e| (Some(e), None))?;
1217
1218        // Find plugins that are not dependencies of other plugins
1219        let result: Vec<_> = self
1220            .plugins
1221            .par_iter()
1222            .enumerate()
1223            .filter_map(|(index, plugin)| {
1224                let find_plugin = self.plugins.iter().find(|pl| {
1225                    pl.info
1226                        .info
1227                        .depends()
1228                        .iter()
1229                        .chain(pl.info.info.optional_depends().iter())
1230                        .any(|d| {
1231                            *d == plugin.info.bundle
1232                                && self
1233                                    .plugins
1234                                    .iter()
1235                                    .find(|p| {
1236                                        d.version.matches(&p.info.bundle.version)
1237                                            && p.info.bundle.version > plugin.info.bundle.version
1238                                    })
1239                                    .is_none()
1240                        })
1241                });
1242
1243                match find_plugin {
1244                    Some(_) => None,
1245                    None => Some(index),
1246                }
1247            })
1248            .collect();
1249
1250        let this = Ptr::new(self);
1251        result.into_par_iter().try_for_each(move |index| {
1252            private_loader::load_plugin(this.as_mut(), index).map_err(|e| (None, Some(e)))
1253        })?;
1254
1255        Ok(bundles)
1256    }
1257
1258    /// Loads only the plugins that are used (not dependencies of other plugins).
1259    ///
1260    /// This method registers and loads only the plugins that are not dependencies of other plugins,
1261    /// and automatically unregisters unused plugins.
1262    ///
1263    /// # Parameters
1264    ///
1265    /// * `paths` - Iterator of paths to plugin files or directories
1266    ///
1267    /// # Returns
1268    ///
1269    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<UnregisterPluginError>, Option<LoadPluginError>)>`
1270    /// containing the plugin bundles on success, or errors from registration, unregistration, or loading.
1271    ///
1272    /// # Type Parameters
1273    ///
1274    /// * `'b` - Lifetime of the path references
1275    /// * `P` - Type of the iterator containing path references
1276    pub fn load_only_used_plugins<'b, P>(
1277        &mut self,
1278        paths: P,
1279    ) -> Result<
1280        Vec<Bundle>,
1281        (
1282            Option<RegisterPluginError>,
1283            Option<UnregisterPluginError>,
1284            Option<LoadPluginError>,
1285        ),
1286    >
1287    where
1288        P: IntoIterator<Item = &'b str>,
1289    {
1290        let mut bundles = self
1291            .register_plugins(paths)
1292            .map_err(|e| (Some(e), None, None))?;
1293
1294        // Find plugins that are not dependencies of other plugins
1295        let (used, unused): (Vec<_>, Vec<_>) = self
1296            .plugins
1297            .iter()
1298            .enumerate()
1299            .filter_map(|(index, plugin)| {
1300                let find_plugin = self.plugins.iter().find(|pl| {
1301                    pl.info
1302                        .info
1303                        .depends()
1304                        .iter()
1305                        .chain(pl.info.info.optional_depends().iter())
1306                        .any(|d| {
1307                            *d == plugin.info.bundle
1308                                && self
1309                                    .plugins
1310                                    .iter()
1311                                    .find(|p| {
1312                                        d.version.matches(&p.info.bundle.version)
1313                                            && p.info.bundle.version > plugin.info.bundle.version
1314                                    })
1315                                    .is_none()
1316                        })
1317                });
1318
1319                match find_plugin {
1320                    Some(_) => None,
1321                    None => Some(index),
1322                }
1323            })
1324            .partition(|index| {
1325                let bundle = &self.plugins[*index].info.bundle;
1326
1327                // Find the highest version
1328                self.plugins
1329                    .iter()
1330                    .find(|pl| {
1331                        pl.info.bundle.id == bundle.id && pl.info.bundle.version > bundle.version
1332                    })
1333                    .is_none()
1334            });
1335
1336        used.into_iter().try_for_each(|index| {
1337            private_loader::load_plugin(self, index).map_err(|e| (None, None, Some(e)))
1338        })?;
1339
1340        let mut old_indexs = vec![];
1341        let mut unused = unused.into_iter();
1342
1343        while let Some(index) = unused.next() {
1344            let swap = old_indexs
1345                .iter()
1346                .fold(0, |acc, i| if index > *i { acc + 1 } else { acc });
1347
1348            let new_index = index - swap;
1349
1350            let bundle = &self.plugins[new_index].info.bundle;
1351            bundles.retain(|b| *b != *bundle);
1352
1353            private_loader::unregister_plugin(&mut self.plugins, new_index)
1354                .map_err(|e| (None, Some(e), None))?;
1355
1356            old_indexs.push(index);
1357        }
1358
1359        Ok(bundles)
1360    }
1361
1362    /// Loads only the plugins that are used (not dependencies of other plugins) (parallel version).
1363    ///
1364    /// This method registers and loads only the plugins that are not dependencies of other plugins
1365    /// using parallel processing, and automatically unregisters unused plugins.
1366    ///
1367    /// # Parameters
1368    ///
1369    /// * `paths` - Parallel iterator of paths to plugin files or directories
1370    ///
1371    /// # Returns
1372    ///
1373    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<UnregisterPluginError>, Option<LoadPluginError>)>`
1374    /// containing the plugin bundles on success, or errors from registration, unregistration, or loading.
1375    ///
1376    /// # Type Parameters
1377    ///
1378    /// * `'b` - Lifetime of the path references
1379    /// * `P` - Type of the parallel iterator containing path references
1380    pub fn par_load_only_used_plugins<'b, P>(
1381        &mut self,
1382        paths: P,
1383    ) -> Result<
1384        Vec<Bundle>,
1385        (
1386            Option<RegisterPluginError>,
1387            Option<UnregisterPluginError>,
1388            Option<LoadPluginError>,
1389        ),
1390    >
1391    where
1392        P: IntoParallelIterator<Item = &'b str>,
1393    {
1394        let bundles = self
1395            .par_register_plugins(paths)
1396            .map_err(|e| (Some(e), None, None))?;
1397
1398        // Find plugins that are not dependencies of other plugins
1399        let (used, unused): (Vec<_>, Vec<_>) = self
1400            .plugins
1401            .iter()
1402            .enumerate()
1403            .filter_map(|(index, plugin)| {
1404                let find_plugin = self.plugins.iter().find(|pl| {
1405                    pl.info
1406                        .info
1407                        .depends()
1408                        .iter()
1409                        .chain(pl.info.info.optional_depends().iter())
1410                        .any(|d| {
1411                            *d == plugin.info.bundle
1412                                && self
1413                                    .plugins
1414                                    .iter()
1415                                    .find(|p| {
1416                                        d.version.matches(&p.info.bundle.version)
1417                                            && p.info.bundle.version > plugin.info.bundle.version
1418                                    })
1419                                    .is_none()
1420                        })
1421                });
1422
1423                match find_plugin {
1424                    Some(_) => None,
1425                    None => Some(index),
1426                }
1427            })
1428            .partition(|index| {
1429                let bundle = &self.plugins[*index].info.bundle;
1430
1431                // Find the highest version
1432                self.plugins
1433                    .iter()
1434                    .find(|pl| {
1435                        pl.info.bundle.id == bundle.id && pl.info.bundle.version > bundle.version
1436                    })
1437                    .is_none()
1438            });
1439
1440        let this = Ptr::new(self);
1441        used.into_iter().try_for_each(|index| {
1442            private_loader::load_plugin(this.as_mut(), index).map_err(|e| (None, None, Some(e)))
1443        })?;
1444
1445        let mut old_indexs = vec![];
1446        let mut unused = unused.into_iter();
1447
1448        while let Some(index) = unused.next() {
1449            let swap = old_indexs
1450                .iter()
1451                .fold(0, |acc, i| if index > *i { acc + 1 } else { acc });
1452
1453            private_loader::unregister_plugin(&mut this.as_mut().plugins, index - swap)
1454                .map_err(|e| (None, Some(e), None))?;
1455
1456            old_indexs.push(index);
1457        }
1458
1459        Ok(bundles)
1460    }
1461}
1462
1463impl<O: Send + Sync, I: Info> Drop for Loader<'_, O, I> {
1464    fn drop(&mut self) {
1465        self.stop().unwrap();
1466    }
1467}
1468
1469mod private_loader {
1470    use std::path::Path;
1471
1472    use crate::{
1473        Api, Bundle, Depend, Info, LoadPluginContext, Manager, Plugin, PluginInfo,
1474        RegisterPluginContext,
1475        utils::{
1476            LoadPluginError, Ptr, RegisterManagerError, RegisterPluginError, StopLoaderError,
1477            UnloadPluginError, UnregisterManagerError, UnregisterPluginError,
1478        },
1479    };
1480
1481    pub fn stop_plugins<O: Send + Sync, I: Info>(
1482        loader: &mut super::Loader<'_, O, I>,
1483    ) -> Result<(), StopLoaderError> {
1484        // Sort plugins in order of their dependencies
1485        let sort_plugins = sort_plugins(
1486            &loader.plugins,
1487            loader
1488                .plugins
1489                .iter()
1490                .enumerate()
1491                .map(|(index, _)| index)
1492                .collect(),
1493        );
1494
1495        // Unload plugins
1496        let errors = sort_plugins
1497            .iter()
1498            .map(|index| {
1499                forced_unload_plugin(&mut loader.plugins, index.clone())
1500                    .map_err(|e| UnregisterPluginError::UnloadError(e))
1501            })
1502            .partition::<Vec<_>, _>(|r| r.is_err())
1503            .0;
1504
1505        if !errors.is_empty() {
1506            return Err(StopLoaderError::UnregisterPluginFailed(
1507                errors.into_iter().map(|r| r.err().unwrap()).collect(),
1508            ));
1509        }
1510
1511        //TODO: Add debug output
1512        let errors = (0..loader.plugins.len())
1513            .map(|_| forced_unregister_plugin(&mut loader.plugins, 0_usize))
1514            .partition::<Vec<_>, _>(|r| r.is_err())
1515            .0;
1516
1517        match !errors.is_empty() {
1518            true => Err(StopLoaderError::UnregisterPluginFailed(
1519                errors.into_iter().map(|r| r.err().unwrap()).collect(),
1520            )),
1521            false => Ok(()),
1522        }
1523    }
1524
1525    pub fn stop_managers<'a, O: Send + Sync, I: Info>(
1526        loader: &'a mut super::Loader<'_, O, I>,
1527    ) -> Result<(), StopLoaderError> {
1528        // Detach plugin managers from the loader
1529        let mut errors = vec![];
1530        while !loader.managers.is_empty() {
1531            if let Err(e) = forced_unregister_manager(&mut loader.managers, 0_usize) {
1532                errors.push(e);
1533            }
1534        }
1535
1536        match !errors.is_empty() {
1537            true => Err(StopLoaderError::UnregisterManagerFailed(errors)),
1538            false => Ok(()),
1539        }
1540    }
1541
1542    /*
1543        TODO: Change plugin sorting.
1544        The function arguments must pass a list of all plugins
1545        and an optional set of plugin indexes for targeted sorting.
1546        The output should provide the index of the beginning of sorted plugins.
1547
1548        Mechanics of sorting consists in shifting to the end of the plugin list
1549        while sorting them.
1550    */
1551    // pub fn sort_plugins<'a, O: Send + Sync, I: Info>(
1552    //     plugins: &mut Vec<Plugin<'a, O, I>>,
1553    //     plugins_set: Option<Vec<usize>>,
1554    // ) -> usize
1555
1556    // Advanced tree sorting
1557    pub fn sort_plugins<'a, O: Send + Sync, I: Info>(
1558        plugins: &Vec<Plugin<'a, O, I>>,
1559        plugins_set: Vec<usize>,
1560    ) -> Vec<usize> {
1561        let mut result = vec![];
1562
1563        'outer: for index in plugins_set.iter() {
1564            let bundle = &plugins[*index].info.bundle;
1565
1566            let find_plugin = plugins.iter().enumerate().find_map(|(i, pl)| {
1567                pl.info
1568                    .info
1569                    .depends()
1570                    .iter()
1571                    .chain(pl.info.info.optional_depends().iter())
1572                    .any(|d| {
1573                        *d == *bundle
1574                            && plugins
1575                                .iter()
1576                                .find(|p| {
1577                                    d.version.matches(&p.info.bundle.version)
1578                                        && p.info.bundle.version > bundle.version
1579                                })
1580                                .is_none()
1581                    })
1582                    .then_some(i)
1583            });
1584
1585            if find_plugin.is_some()
1586                && plugins_set
1587                    .iter()
1588                    .find(|i| **i == find_plugin.unwrap())
1589                    .is_some()
1590            {
1591                continue 'outer;
1592            }
1593
1594            sort_pick(plugins, &plugins_set, index, &mut result);
1595        }
1596
1597        result
1598    }
1599
1600    pub fn sort_pick<'a, O: Send + Sync, I: Info>(
1601        plugins: &Vec<Plugin<'a, O, I>>,
1602        plugins_set: &Vec<usize>,
1603        index: &usize,
1604        result: &mut Vec<usize>,
1605    ) {
1606        result.push(index.clone());
1607
1608        let plugin_info = &plugins[*index].info;
1609        let depends = plugin_info
1610            .info
1611            .depends()
1612            .iter()
1613            .chain(plugin_info.info.optional_depends().iter());
1614        'outer: for depend in depends {
1615            if !result.iter().any(|inx| {
1616                *depend == plugins[*inx].info.bundle
1617                    && plugins
1618                        .iter()
1619                        .find(|p| {
1620                            depend.version.matches(&p.info.bundle.version)
1621                                && p.info.bundle.version > plugins[*inx].info.bundle.version
1622                        })
1623                        .is_none()
1624            }) {
1625                let mut plugin = None;
1626
1627                for index in plugins_set.iter() {
1628                    let plug_info = &plugins[*index].info;
1629                    if *depend == plug_info.bundle
1630                        && plugins
1631                            .iter()
1632                            .find(|p| {
1633                                depend.version.matches(&p.info.bundle.version)
1634                                    && p.info.bundle.version > plug_info.bundle.version
1635                            })
1636                            .is_none()
1637                    {
1638                        plugin = Some(index);
1639                        continue;
1640                    }
1641
1642                    if !result
1643                        .iter()
1644                        .any(|inx| plugins[*inx].info.bundle == plug_info.bundle)
1645                        && (plug_info.info.depends().contains(depend)
1646                            || plug_info.info.optional_depends().contains(depend))
1647                    {
1648                        continue 'outer;
1649                    }
1650                }
1651
1652                if let Some(index) = plugin {
1653                    sort_pick(plugins, plugins_set, index, result);
1654                }
1655            }
1656        }
1657    }
1658
1659    pub fn forced_register_manager<'a, O: Send + Sync, I: Info>(
1660        loader: &mut super::Loader<'a, O, I>,
1661        mut manager: Box<dyn Manager<'a, O, I>>,
1662    ) -> Result<(), RegisterManagerError> {
1663        manager.as_mut().register_manager()?;
1664        loader.managers.push(manager);
1665        Ok(())
1666    }
1667
1668    pub fn register_manager<'a, O: Send + Sync, I: Info>(
1669        loader: &mut super::Loader<'a, O, I>,
1670        manager: Box<dyn Manager<'a, O, I>>,
1671    ) -> Result<(), RegisterManagerError> {
1672        if let Some(_) = loader.managers.iter().find(|m| manager == **m) {
1673            return Err(RegisterManagerError::AlreadyOccupiedFormat(
1674                manager.format().to_string(),
1675            ));
1676        }
1677
1678        forced_register_manager(loader, manager)
1679    }
1680
1681    pub fn forced_unregister_manager<O: Send + Sync, I: Info>(
1682        managers: &mut Vec<Box<dyn Manager<'_, O, I>>>,
1683        index: usize,
1684    ) -> Result<(), UnregisterManagerError> {
1685        match managers.remove(index).unregister_manager() {
1686            Ok(_) => Ok(()),
1687            Err(e) => Err(UnregisterManagerError::UnregisterManagerByManager(e)),
1688        }
1689    }
1690
1691    pub fn unregister_manager<O: Send + Sync, I: Info>(
1692        loader: &mut super::Loader<'_, O, I>,
1693        index: usize,
1694    ) -> Result<(), UnregisterManagerError> {
1695        let manager = &loader.managers[index];
1696
1697        // Get all plugins related to the manager
1698        let plugins_from_manager = loader
1699            .plugins
1700            .iter()
1701            .enumerate()
1702            .filter_map(
1703                |(index, plugin)| match *plugin.manager.as_ref() == *manager {
1704                    true => Some(index),
1705                    false => None,
1706                },
1707            )
1708            .collect();
1709
1710        // Sort manager plugins in order of their dependencies
1711        let sort_plugins = sort_plugins(&loader.plugins, plugins_from_manager);
1712
1713        // Unload plugins
1714        for index in sort_plugins.iter() {
1715            unload_plugin(&mut loader.plugins, index.clone()).map_err(|e| {
1716                UnregisterManagerError::UnregisterPlugin(UnregisterPluginError::UnloadError(e))
1717            })?;
1718        }
1719
1720        let mut old_indexs = vec![];
1721        let mut sort_plugins = sort_plugins.into_iter();
1722
1723        while let Some(index) = sort_plugins.next() {
1724            let swap = old_indexs
1725                .iter()
1726                .fold(0, |acc, i| if index > *i { acc + 1 } else { acc });
1727
1728            forced_unregister_plugin(&mut loader.plugins, index - swap)
1729                .map_err(|e| UnregisterManagerError::UnregisterPlugin(e))?;
1730
1731            old_indexs.push(index);
1732        }
1733
1734        // Unload manager
1735        forced_unregister_manager(&mut loader.managers, index)
1736    }
1737
1738    pub fn forced_register_plugin<'a, O: Send + Sync, I: Info>(
1739        plugins: &mut Vec<Plugin<'a, O, I>>,
1740        manager: Ptr<'a, Box<dyn Manager<'a, O, I>>>,
1741        plugin_info: PluginInfo<I>,
1742    ) -> Result<Bundle, RegisterPluginError> {
1743        let bundle = plugin_info.bundle.clone();
1744        plugins.push(Plugin::<'a>::new(manager, plugin_info));
1745        Ok(bundle)
1746    }
1747
1748    pub fn register_plugin<'a, O: Send + Sync, I: Info>(
1749        loader: &mut super::Loader<'a, O, I>,
1750        path: &str,
1751    ) -> Result<Bundle, RegisterPluginError> {
1752        let path = Path::new(path).to_path_buf();
1753
1754        if !path.is_dir() {
1755            return Err(RegisterPluginError::NotFound);
1756        }
1757
1758        if let None = path.extension() {
1759            return Err(RegisterPluginError::UnknownManagerFormat("".to_string()));
1760        }
1761
1762        let bundle = Bundle::from_filename(path.file_name().unwrap())?;
1763
1764        // Check if such a plugin already exists
1765        if loader.get_plugin_by_bundle(&bundle).is_some() {
1766            return Err(RegisterPluginError::AlreadyExistsIDAndVersion(
1767                bundle.id.clone(),
1768                bundle.version.clone(),
1769            ));
1770        }
1771
1772        // Looking for a suitable manager
1773        let plugin_format = bundle.format.clone();
1774        let manager = loader
1775            .get_manager_mut(plugin_format.as_str())
1776            .ok_or(RegisterPluginError::UnknownManagerFormat(plugin_format))?;
1777
1778        // Manager registers plugin
1779        let info = manager.register_plugin(RegisterPluginContext {
1780            path: &path,
1781            bundle: &bundle,
1782        })?;
1783        let plugin_info = PluginInfo { path, bundle, info };
1784
1785        // Register plugin
1786        let manager = Ptr::<'a>::new(manager);
1787        forced_register_plugin(&mut loader.plugins, manager, plugin_info)
1788    }
1789
1790    pub fn forced_unregister_plugin<O: Send + Sync, I: Info>(
1791        plugins: &mut Vec<Plugin<'_, O, I>>,
1792        index: usize,
1793    ) -> Result<(), UnregisterPluginError> {
1794        let plugin = plugins.remove(index);
1795        plugin.manager.as_mut().unregister_plugin(&plugin)?;
1796        Ok(())
1797    }
1798
1799    pub fn unregister_plugin<'a, O: Send + Sync, I: Info>(
1800        plugins: &mut Vec<Plugin<'_, O, I>>,
1801        index: usize,
1802    ) -> Result<(), UnregisterPluginError> {
1803        unload_plugin(plugins, index)?;
1804        forced_unregister_plugin(plugins, index)
1805    }
1806
1807    pub fn forced_load_plugin<O: Send + Sync, I: Info>(
1808        loader: *mut super::Loader<'static, O, I>,
1809        index: usize,
1810        depends: Vec<(Bundle, bool)>,
1811    ) -> Result<(), LoadPluginError> {
1812        let manager = Ptr::new(unsafe { &*loader }.plugins[index].manager.as_ptr());
1813
1814        // Get plugin and its dependencies
1815        let plugin = &mut unsafe { &mut *loader }.plugins[index];
1816
1817        // Split dependencies
1818        let mut deps = vec![];
1819        let mut opt_deps = vec![];
1820
1821        for (bundle, is_depend) in depends {
1822            match is_depend {
1823                true => deps.push(bundle),
1824                false => opt_deps.push(bundle),
1825            }
1826        }
1827
1828        // Load plugin
1829        let bundle = plugin.info.bundle.clone();
1830
1831        manager.as_mut().load_plugin(
1832            LoadPluginContext::new(plugin, &unsafe { &*loader }.requests),
1833            Api::new(Ptr::new(loader), bundle, deps, opt_deps),
1834        )?;
1835
1836        plugin.is_load = true;
1837
1838        Ok(())
1839    }
1840
1841    fn load_depends<'a, O, I, IT>(
1842        loader: &'a mut super::Loader<'static, O, I>,
1843        depends_iter: IT,
1844    ) -> Result<(Vec<(Bundle, bool)>, Vec<Depend>), LoadPluginError>
1845    where
1846        O: Send + Sync,
1847        I: Info,
1848        IT: IntoIterator<Item = (bool, Depend)>,
1849    {
1850        let mut found_depends = vec![];
1851        let mut not_found_depends = vec![];
1852
1853        for (is_depend, depend) in depends_iter.into_iter() {
1854            if let Some((index, plugin)) = loader.plugins.iter().enumerate().find(|(_, plugin)| {
1855                depend == plugin.info.bundle
1856                    && loader
1857                        .plugins
1858                        .iter()
1859                        .find(|p| {
1860                            depend.version.matches(&p.info.bundle.version)
1861                                && p.info.bundle.version > plugin.info.bundle.version
1862                        })
1863                        .is_none()
1864            }) {
1865                found_depends.push((plugin.info.bundle.clone(), is_depend));
1866                load_plugin(loader, index).map_err(|e| LoadPluginError::LoadDependency {
1867                    depend: depend,
1868                    error: Box::new(e),
1869                })?;
1870            } else if is_depend {
1871                not_found_depends.push(depend);
1872            }
1873        }
1874        Ok((found_depends, not_found_depends))
1875    }
1876
1877    fn check_requests<O: Send + Sync, I: Info>(
1878        loader: &mut super::Loader<'static, O, I>,
1879        index: usize,
1880    ) -> Vec<String> {
1881        let mut plugin_requests = loader.plugins[index].requests.iter();
1882        loader
1883            .requests
1884            .iter()
1885            .filter_map(|req| match plugin_requests.any(|r| r.name() == req.name) {
1886                true => None,
1887                false => Some(req.name.clone()),
1888            })
1889            .collect()
1890    }
1891
1892    pub fn load_plugin<O: Send + Sync, I: Info>(
1893        loader: &mut super::Loader<'static, O, I>,
1894        index: usize,
1895    ) -> Result<(), LoadPluginError> {
1896        if loader.plugins[index].is_load {
1897            return Ok(());
1898        }
1899
1900        // Load dependencies
1901        let info = &loader.plugins[index].info;
1902        let depends_iter = info
1903            .info
1904            .depends()
1905            .clone()
1906            .into_iter()
1907            .map(|d| (true, d))
1908            .chain(
1909                info.info
1910                    .optional_depends()
1911                    .clone()
1912                    .into_iter()
1913                    .map(|d| (false, d)),
1914            );
1915        let (found_depends, not_found_depends) = load_depends(loader, depends_iter)?;
1916
1917        if !not_found_depends.is_empty() {
1918            return Err(LoadPluginError::NotFoundDependencies(not_found_depends));
1919        }
1920
1921        // Load plugin
1922        forced_load_plugin(loader, index, found_depends)?;
1923
1924        // Check for requested functions
1925        let not_found_requests = check_requests(loader, index);
1926
1927        if !not_found_requests.is_empty() {
1928            loader.plugins[index].is_load = false;
1929            return Err(LoadPluginError::RequestsNotFound(not_found_requests));
1930        }
1931
1932        Ok(())
1933    }
1934
1935    pub fn forced_unload_plugin<O: Send + Sync, I: Info>(
1936        plugins: &mut Vec<Plugin<'_, O, I>>,
1937        index: usize,
1938    ) -> Result<(), UnloadPluginError> {
1939        if plugins[index].is_load {
1940            plugins[index]
1941                .manager
1942                .as_mut()
1943                .unload_plugin(&plugins[index])?;
1944        }
1945
1946        plugins[index].is_load = false;
1947
1948        Ok(())
1949    }
1950
1951    pub fn unload_plugin<'a, O: Send + Sync, I: Info>(
1952        plugins: &mut Vec<Plugin<'_, O, I>>,
1953        index: usize,
1954    ) -> Result<(), UnloadPluginError> {
1955        if plugins[index].is_load {
1956            let bundle = &plugins[index].info.bundle;
1957
1958            // Check that the plugin is not used as a dependency by loaded plugins
1959            plugins.iter().try_for_each(|plug| {
1960                let plug_info = &plug.info;
1961
1962                let find_depend = plug_info
1963                    .info
1964                    .depends()
1965                    .iter()
1966                    .chain(plug_info.info.optional_depends().iter())
1967                    .find(|depend| {
1968                        **depend == *bundle
1969                            && plugins
1970                                .iter()
1971                                .find(|p| {
1972                                    depend.version.matches(&p.info.bundle.version)
1973                                        && p.info.bundle.version > bundle.version
1974                                })
1975                                .is_none()
1976                    })
1977                    .is_some();
1978                match plug.is_load && find_depend {
1979                    true => Err(UnloadPluginError::CurrentlyUsesDepend {
1980                        plugin: plug_info.bundle.clone(),
1981                        depend: bundle.clone(),
1982                    }),
1983                    false => Ok(()),
1984                }
1985            })?;
1986        }
1987
1988        forced_unload_plugin(plugins, index)
1989    }
1990}