plux_rs/
api.rs

1use rayon::prelude::IntoParallelIterator;
2use semver::Version;
3
4use crate::{
5    Bundle, Info, Loader, Manager, Plugin, Registry, Requests,
6    utils::{
7        CallFunctionDependError, LoadPluginError, PluginCallFunctionError, PluginCallRequestError,
8        PluginOperationError, Ptr, RegisterManagerError, RegisterPluginError, UnloadPluginError,
9        UnregisterManagerError, UnregisterPluginError,
10    },
11    variable::Variable,
12};
13
14/// API interface provided to plugins during loading.
15///
16/// The Api struct provides a controlled interface for plugins to interact with the Plux system.
17/// It allows plugins to access the loader's functionality while maintaining security boundaries
18/// and providing dependency-aware operations.
19///
20/// # Type Parameters
21///
22/// * `O` - Output type for plugin functions (must implement Send + Sync + 'static)
23/// * `I` - Plugin information type (must implement Info + 'static)
24///
25/// # Fields
26///
27/// * `loader` - Reference to the underlying loader
28/// * `plugin` - Bundle information for the current plugin
29/// * `depends` - List of required dependencies for this plugin
30/// * `optional_depends` - List of optional dependencies for this plugin
31pub struct Api<O: Send + Sync + 'static, I: Info + 'static> {
32    loader: Ptr<'static, Loader<'static, O, I>>,
33    plugin: Bundle,
34    depends: Vec<Bundle>,
35    optional_depends: Vec<Bundle>,
36}
37
38impl<O: Send + Sync + 'static, I: Info + 'static> Api<O, I> {
39    /// Creates a new API instance for a plugin.
40    ///
41    /// This is an internal constructor used by the loader when loading plugins.
42    ///
43    /// # Parameters
44    ///
45    /// * `loader` - Reference to the loader
46    /// * `plugin` - Bundle information for the plugin
47    /// * `depends` - Required dependencies
48    /// * `optional_depends` - Optional dependencies
49    ///
50    /// # Returns
51    ///
52    /// Returns a new Api instance.
53    pub(crate) const fn new(
54        loader: Ptr<'static, Loader<'static, O, I>>,
55        plugin: Bundle,
56        depends: Vec<Bundle>,
57        optional_depends: Vec<Bundle>,
58    ) -> Self {
59        Self {
60            loader,
61            plugin,
62            depends,
63            optional_depends,
64        }
65    }
66
67    /// Gets access to the function registry.
68    ///
69    /// Returns a reference to the registry containing all functions available to plugins.
70    ///
71    /// # Returns
72    ///
73    /// Returns `&Registry<O>` containing the function registry.
74    pub fn registry(&self) -> &Registry<O> {
75        &self.loader.as_ref().registry
76    }
77
78    /// Gets information about the current plugin.
79    ///
80    /// Returns the bundle information for the plugin this API instance belongs to.
81    ///
82    /// # Returns
83    ///
84    /// Returns `&Bundle` containing plugin metadata.
85    pub const fn plugin(&self) -> &Bundle {
86        &self.plugin
87    }
88
89    /// Gets the list of required dependencies.
90    ///
91    /// Returns all dependencies that must be available for this plugin to function.
92    ///
93    /// # Returns
94    ///
95    /// Returns `&Vec<Bundle>` containing required dependencies.
96    pub const fn depends(&self) -> &Vec<Bundle> {
97        &self.depends
98    }
99
100    /// Gets the list of optional dependencies.
101    ///
102    /// Returns all optional dependencies that enhance this plugin's functionality but are not required.
103    ///
104    /// # Returns
105    ///
106    /// Returns `&Vec<Bundle>` containing optional dependencies.
107    pub const fn optional_depends(&self) -> &Vec<Bundle> {
108        &self.optional_depends
109    }
110
111    // Loader functions
112
113    /// Registers a plugin manager with the loader.
114    ///
115    /// This method allows plugins to register new managers during execution.
116    ///
117    /// # Parameters
118    ///
119    /// * `manager` - The manager instance to register
120    ///
121    /// # Returns
122    ///
123    /// Returns `Result<(), RegisterManagerError>` indicating success or failure.
124    ///
125    /// # Type Parameters
126    ///
127    /// * `M` - Type of the manager (must implement Manager trait)
128    pub fn register_manager<M>(&self, manager: M) -> Result<(), RegisterManagerError>
129    where
130        M: Manager<'static, O, I> + 'static,
131    {
132        self.loader.as_mut().register_manager(manager)
133    }
134
135    /// Registers multiple plugin managers with the loader.
136    ///
137    /// This method allows plugins to register multiple managers in sequence.
138    ///
139    /// # Parameters
140    ///
141    /// * `managers` - Iterator of manager instances to register
142    ///
143    /// # Returns
144    ///
145    /// Returns `Result<(), RegisterManagerError>` indicating success or failure.
146    pub fn register_managers<M>(&self, managers: M) -> Result<(), RegisterManagerError>
147    where
148        M: IntoIterator<Item = Box<dyn Manager<'static, O, I>>>,
149    {
150        self.loader.as_mut().register_managers(managers)
151    }
152
153    /// Registers multiple plugin managers with the loader in parallel.
154    ///
155    /// This method allows plugins to register multiple managers concurrently.
156    ///
157    /// # Parameters
158    ///
159    /// * `managers` - Parallel iterator of manager instances to register
160    ///
161    /// # Returns
162    ///
163    /// Returns `Result<(), RegisterManagerError>` indicating success or failure.
164    pub fn par_register_managers<M>(&self, managers: M) -> Result<(), RegisterManagerError>
165    where
166        M: IntoParallelIterator<Item = Box<dyn Manager<'static, O, I>>>,
167    {
168        self.loader.as_mut().par_register_managers(managers)
169    }
170
171    /// Unregisters a plugin manager from the loader.
172    ///
173    /// This method allows plugins to unregister managers by format.
174    ///
175    /// # Parameters
176    ///
177    /// * `format` - The format of the manager to unregister
178    ///
179    /// # Returns
180    ///
181    /// Returns `Result<(), UnregisterManagerError>` indicating success or failure.
182    pub fn unregister_manager(&self, format: &str) -> Result<(), UnregisterManagerError> {
183        self.loader.as_mut().unregister_manager(format)
184    }
185
186    /// Gets an immutable reference to a manager by format.
187    ///
188    /// This method allows plugins to access registered managers.
189    ///
190    /// # Parameters
191    ///
192    /// * `format` - The format of the manager to retrieve
193    ///
194    /// # Returns
195    ///
196    /// Returns `Option<&Box<dyn Manager<'static, O, I>>>` containing the manager if found.
197    pub fn get_manager_ref(&self, format: &str) -> Option<&Box<dyn Manager<'static, O, I>>> {
198        self.loader.as_ref().get_manager_ref(format)
199    }
200
201    /// Gets an immutable reference to a manager by format (parallel version).
202    ///
203    /// This method allows plugins to access registered managers using parallel processing.
204    ///
205    /// # Parameters
206    ///
207    /// * `format` - The format of the manager to retrieve
208    ///
209    /// # Returns
210    ///
211    /// Returns `Option<&Box<dyn Manager<'static, O, I>>>` containing the manager if found.
212    pub fn par_get_manager_ref(&self, format: &str) -> Option<&Box<dyn Manager<'static, O, I>>> {
213        self.loader.as_ref().par_get_manager_ref(format)
214    }
215
216    /// Gets a mutable reference to a manager by format.
217    ///
218    /// This method allows plugins to access registered managers for modification.
219    ///
220    /// # Parameters
221    ///
222    /// * `format` - The format of the manager to retrieve
223    ///
224    /// # Returns
225    ///
226    /// Returns `Option<&mut Box<dyn Manager<'static, O, I>>>` containing the manager if found.
227    pub fn get_manager_mut(&self, format: &str) -> Option<&mut Box<dyn Manager<'static, O, I>>> {
228        self.loader.as_mut().get_manager_mut(format)
229    }
230
231    /// Gets a mutable reference to a manager by format (parallel version).
232    ///
233    /// This method allows plugins to access registered managers for modification using parallel processing.
234    ///
235    /// # Parameters
236    ///
237    /// * `format` - The format of the manager to retrieve
238    ///
239    /// # Returns
240    ///
241    /// Returns `Option<&mut Box<dyn Manager<'static, O, I>>>` containing the manager if found.
242    pub fn par_get_manager_mut(
243        &self,
244        format: &str,
245    ) -> Option<&mut Box<dyn Manager<'static, O, I>>> {
246        self.loader.as_mut().par_get_manager_mut(format)
247    }
248
249    /// Registers a plugin with the loader.
250    ///
251    /// This method allows plugins to register new plugins during execution.
252    ///
253    /// # Parameters
254    ///
255    /// * `path` - Path to the plugin file or directory
256    ///
257    /// # Returns
258    ///
259    /// Returns `Result<Bundle, RegisterPluginError>` containing the plugin bundle on success.
260    pub fn register_plugin(&self, path: &str) -> Result<Bundle, RegisterPluginError> {
261        self.loader.as_mut().register_plugin(path)
262    }
263
264    /// Registers multiple plugins with the loader.
265    ///
266    /// This method allows plugins to register multiple plugins in sequence.
267    ///
268    /// # Parameters
269    ///
270    /// * `paths` - Iterator of paths to plugin files or directories
271    ///
272    /// # Returns
273    ///
274    /// Returns `Result<Vec<Bundle>, RegisterPluginError>` containing the plugin bundles on success.
275    ///
276    /// # Type Parameters
277    ///
278    /// * `'b` - Lifetime of the path references
279    /// * `P` - Type of the iterator containing path references
280    pub fn register_plugins<'b, P>(&self, paths: P) -> Result<Vec<Bundle>, RegisterPluginError>
281    where
282        P: IntoIterator<Item = &'b str>,
283    {
284        self.loader.as_mut().register_plugins(paths)
285    }
286
287    /// Registers multiple plugins with the loader in parallel.
288    ///
289    /// This method allows plugins to register multiple plugins concurrently.
290    ///
291    /// # Parameters
292    ///
293    /// * `paths` - Parallel iterator of paths to plugin files or directories
294    ///
295    /// # Returns
296    ///
297    /// Returns `Result<Vec<Bundle>, RegisterPluginError>` containing the plugin bundles on success.
298    ///
299    /// # Type Parameters
300    ///
301    /// * `'b` - Lifetime of the path references
302    /// * `P` - Type of the parallel iterator containing path references
303    pub fn par_register_plugins<'b, P>(&self, paths: P) -> Result<Vec<Bundle>, RegisterPluginError>
304    where
305        P: IntoParallelIterator<Item = &'b str>,
306    {
307        self.loader.as_mut().par_register_plugins(paths)
308    }
309
310    /// Unregisters a plugin from the loader.
311    ///
312    /// This method allows plugins to unregister plugins by ID and version.
313    ///
314    /// # Parameters
315    ///
316    /// * `id` - Plugin identifier
317    /// * `version` - Plugin version
318    ///
319    /// # Returns
320    ///
321    /// Returns `Result<(), UnregisterPluginError>` indicating success or failure.
322    pub fn unregister_plugin(
323        &self,
324        id: &str,
325        version: &Version,
326    ) -> Result<(), UnregisterPluginError> {
327        self.loader.as_mut().unregister_plugin(id, version)
328    }
329
330    /// Unregisters a plugin from the loader by bundle.
331    ///
332    /// This method allows plugins to unregister plugins by bundle information.
333    ///
334    /// # Parameters
335    ///
336    /// * `bundle` - Plugin bundle information
337    ///
338    /// # Returns
339    ///
340    /// Returns `Result<(), UnregisterPluginError>` indicating success or failure.
341    pub fn unregister_plugin_by_bundle(
342        &self,
343        bundle: &Bundle,
344    ) -> Result<(), UnregisterPluginError> {
345        self.loader.as_mut().unregister_plugin_by_bundle(bundle)
346    }
347
348    /// Unregisters a plugin from the loader by bundle (parallel version).
349    ///
350    /// This method allows plugins to unregister plugins by bundle information using parallel processing.
351    ///
352    /// # Parameters
353    ///
354    /// * `bundle` - Plugin bundle information
355    ///
356    /// # Returns
357    ///
358    /// Returns `Result<(), UnregisterPluginError>` indicating success or failure.
359    pub fn par_unregister_plugin_by_bundle(
360        &self,
361        bundle: &Bundle,
362    ) -> Result<(), UnregisterPluginError> {
363        self.loader.as_mut().par_unregister_plugin_by_bundle(bundle)
364    }
365
366    /// Loads a plugin into the execution environment.
367    ///
368    /// This method allows plugins to load other plugins by ID and version.
369    ///
370    /// # Parameters
371    ///
372    /// * `id` - Plugin identifier
373    /// * `version` - Plugin version
374    ///
375    /// # Returns
376    ///
377    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
378    pub fn load_plugin(&self, id: &str, version: &Version) -> Result<(), LoadPluginError> {
379        self.loader.as_mut().load_plugin(id, version)
380    }
381
382    /// Loads a plugin into the execution environment (parallel version).
383    ///
384    /// This method allows plugins to load other plugins by ID and version using parallel processing.
385    ///
386    /// # Parameters
387    ///
388    /// * `id` - Plugin identifier
389    /// * `version` - Plugin version
390    ///
391    /// # Returns
392    ///
393    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
394    pub fn par_load_plugin(&self, id: &str, version: &Version) -> Result<(), LoadPluginError> {
395        self.loader.as_mut().par_load_plugin(id, version)
396    }
397
398    /// Loads a plugin into the execution environment by bundle.
399    ///
400    /// This method allows plugins to load other plugins by bundle information.
401    ///
402    /// # Parameters
403    ///
404    /// * `bundle` - Plugin bundle information
405    ///
406    /// # Returns
407    ///
408    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
409    pub fn load_plugin_by_bundle(&self, bundle: &Bundle) -> Result<(), LoadPluginError> {
410        self.loader.as_mut().load_plugin_by_bundle(bundle)
411    }
412
413    /// Loads a plugin into the execution environment by bundle (parallel version).
414    ///
415    /// This method allows plugins to load other plugins by bundle information using parallel processing.
416    ///
417    /// # Parameters
418    ///
419    /// * `bundle` - Plugin bundle information
420    ///
421    /// # Returns
422    ///
423    /// Returns `Result<(), LoadPluginError>` indicating success or failure.
424    pub fn par_load_plugin_by_bundle(&self, bundle: &Bundle) -> Result<(), LoadPluginError> {
425        self.loader.as_mut().par_load_plugin_by_bundle(bundle)
426    }
427
428    /// Loads a plugin immediately from the specified path.
429    ///
430    /// This convenience method allows plugins to register and load a plugin in a single operation.
431    ///
432    /// # Parameters
433    ///
434    /// * `path` - Path to the plugin file or directory
435    ///
436    /// # Returns
437    ///
438    /// Returns `Result<Bundle, PluginOperationError>`
439    /// containing the plugin bundle on success, or errors from registration or loading.
440    pub fn load_plugin_now(&self, path: &str) -> Result<Bundle, PluginOperationError> {
441        self.loader.as_mut().load_plugin_now(path)
442    }
443
444    /// Loads multiple plugins from the specified paths.
445    ///
446    /// This method allows plugins to register and load multiple plugins in sequence.
447    ///
448    /// # Parameters
449    ///
450    /// * `paths` - Iterator of paths to plugin files or directories
451    ///
452    /// # Returns
453    ///
454    /// Returns `Result<Vec<Bundle>, PluginOperationError>`
455    /// containing the plugin bundles on success, or errors from registration or loading.
456    ///
457    /// # Type Parameters
458    ///
459    /// * `'b` - Lifetime of the path references
460    /// * `P` - Type of the iterator containing path references
461    pub fn load_plugins<'b, P>(&self, paths: P) -> Result<Vec<Bundle>, PluginOperationError>
462    where
463        P: IntoIterator<Item = &'b str>,
464    {
465        self.loader.as_mut().load_plugins(paths)
466    }
467
468    /// Loads multiple plugins from the specified paths (parallel version).
469    ///
470    /// This method allows plugins to register and load multiple plugins concurrently.
471    ///
472    /// # Parameters
473    ///
474    /// * `paths` - Parallel iterator of paths to plugin files or directories
475    ///
476    /// # Returns
477    ///
478    /// Returns `Result<Vec<Bundle>, PluginOperationError>`
479    /// containing the plugin bundles on success, or errors from registration or loading.
480    ///
481    /// # Type Parameters
482    ///
483    /// * `'b` - Lifetime of the path references
484    /// * `P` - Type of the parallel iterator containing path references
485    pub fn par_load_plugins<'b, P>(&self, paths: P) -> Result<Vec<Bundle>, PluginOperationError>
486    where
487        P: IntoParallelIterator<Item = &'b str>,
488    {
489        self.loader.as_mut().par_load_plugins(paths)
490    }
491
492    /// Loads only the plugins that are used (not dependencies of other plugins).
493    ///
494    /// This method allows plugins to register and load only the plugins that are not
495    /// dependencies of other plugins, and automatically unregisters unused plugins.
496    ///
497    /// # Parameters
498    ///
499    /// * `paths` - Iterator of paths to plugin files or directories
500    ///
501    /// # Returns
502    ///
503    /// Returns `Result<Vec<Bundle>, PluginOperationError>`
504    /// containing the plugin bundles on success, or errors from registration, unregistration, or loading.
505    ///
506    /// # Type Parameters
507    ///
508    /// * `'b` - Lifetime of the path references
509    /// * `P` - Type of the iterator containing path references
510    pub fn load_only_used_plugins<'b, P>(
511        &self,
512        paths: P,
513    ) -> Result<Vec<Bundle>, PluginOperationError>
514    where
515        P: IntoIterator<Item = &'b str>,
516    {
517        self.loader.as_mut().load_only_used_plugins(paths)
518    }
519
520    /// Loads only the plugins that are used (not dependencies of other plugins) (parallel version).
521    ///
522    /// This method allows plugins to register and load only the plugins that are not
523    /// dependencies of other plugins using parallel processing, and automatically unregisters unused plugins.
524    ///
525    /// # Parameters
526    ///
527    /// * `paths` - Parallel iterator of paths to plugin files or directories
528    ///
529    /// # Returns
530    ///
531    /// Returns `Result<Vec<Bundle>, PluginOperationError>`
532    /// containing the plugin bundles on success, or errors from registration, unregistration, or loading.
533    ///
534    /// # Type Parameters
535    ///
536    /// * `'b` - Lifetime of the path references
537    /// * `P` - Type of the parallel iterator containing path references
538    pub fn par_load_only_used_plugins<'b, P>(
539        &self,
540        paths: P,
541    ) -> Result<Vec<Bundle>, PluginOperationError>
542    where
543        P: IntoParallelIterator<Item = &'b str>,
544    {
545        self.loader.as_mut().par_load_only_used_plugins(paths)
546    }
547
548    /// Unloads a plugin from the execution environment.
549    ///
550    /// This method allows plugins to unload other plugins by ID and version.
551    ///
552    /// # Parameters
553    ///
554    /// * `id` - Plugin identifier
555    /// * `version` - Plugin version
556    ///
557    /// # Returns
558    ///
559    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
560    pub fn unload_plugin(&self, id: &str, version: &Version) -> Result<(), UnloadPluginError> {
561        self.loader.as_mut().unload_plugin(id, version)
562    }
563
564    /// Unloads a plugin from the execution environment (parallel version).
565    ///
566    /// This method allows plugins to unload other plugins by ID and version using parallel processing.
567    ///
568    /// # Parameters
569    ///
570    /// * `id` - Plugin identifier
571    /// * `version` - Plugin version
572    ///
573    /// # Returns
574    ///
575    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
576    pub fn par_unload_plugin(&self, id: &str, version: &Version) -> Result<(), UnloadPluginError> {
577        self.loader.as_mut().par_unload_plugin(id, version)
578    }
579
580    /// Unloads a plugin from the execution environment by bundle.
581    ///
582    /// This method allows plugins to unload other plugins by bundle information.
583    ///
584    /// # Parameters
585    ///
586    /// * `bundle` - Plugin bundle information
587    ///
588    /// # Returns
589    ///
590    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
591    pub fn unload_plugin_by_bundle(&self, bundle: &Bundle) -> Result<(), UnloadPluginError> {
592        self.loader.as_mut().unload_plugin_by_bundle(bundle)
593    }
594
595    /// Unloads a plugin from the execution environment by bundle (parallel version).
596    ///
597    /// This method allows plugins to unload other plugins by bundle information using parallel processing.
598    ///
599    /// # Parameters
600    ///
601    /// * `bundle` - Plugin bundle information
602    ///
603    /// # Returns
604    ///
605    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
606    pub fn par_unload_plugin_by_bundle(&self, bundle: &Bundle) -> Result<(), UnloadPluginError> {
607        self.loader.as_mut().par_unload_plugin_by_bundle(bundle)
608    }
609
610    /// Gets an immutable reference to a plugin by ID and version.
611    ///
612    /// This method allows plugins to access other registered plugins.
613    ///
614    /// # Parameters
615    ///
616    /// * `id` - Plugin identifier
617    /// * `version` - Plugin version
618    ///
619    /// # Returns
620    ///
621    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
622    pub fn get_plugin(&self, id: &str, version: &Version) -> Option<&Plugin<'static, O, I>> {
623        self.loader.as_ref().get_plugin(id, version)
624    }
625
626    /// Gets an immutable reference to a plugin by ID and version (parallel version).
627    ///
628    /// This method allows plugins to access other registered plugins using parallel processing.
629    ///
630    /// # Parameters
631    ///
632    /// * `id` - Plugin identifier
633    /// * `version` - Plugin version
634    ///
635    /// # Returns
636    ///
637    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
638    pub fn par_get_plugin(&self, id: &str, version: &Version) -> Option<&Plugin<'static, O, I>> {
639        self.loader.as_ref().par_get_plugin(id, version)
640    }
641
642    /// Gets an immutable reference to a plugin by bundle.
643    ///
644    /// This method allows plugins to access other registered plugins by bundle information.
645    ///
646    /// # Parameters
647    ///
648    /// * `bundle` - Plugin bundle information
649    ///
650    /// # Returns
651    ///
652    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
653    pub fn get_plugin_by_bundle(&self, bundle: &Bundle) -> Option<&Plugin<'static, O, I>> {
654        self.loader.as_ref().get_plugin_by_bundle(bundle)
655    }
656
657    /// Gets an immutable reference to a plugin by bundle (parallel version).
658    ///
659    /// This method allows plugins to access other registered plugins by bundle information using parallel processing.
660    ///
661    /// # Parameters
662    ///
663    /// * `bundle` - Plugin bundle information
664    ///
665    /// # Returns
666    ///
667    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
668    pub fn par_get_plugin_by_bundle(&self, bundle: &Bundle) -> Option<&Plugin<'static, O, I>> {
669        self.loader.as_ref().par_get_plugin_by_bundle(bundle)
670    }
671
672    /// Gets a mutable reference to a plugin by ID and version.
673    ///
674    /// This method allows plugins to access other registered plugins for modification.
675    ///
676    /// # Parameters
677    ///
678    /// * `id` - Plugin identifier
679    /// * `version` - Plugin version
680    ///
681    /// # Returns
682    ///
683    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
684    pub fn get_plugin_mut(
685        &self,
686        id: &str,
687        version: &Version,
688    ) -> Option<&mut Plugin<'static, O, I>> {
689        self.loader.as_mut().get_plugin_mut(id, version)
690    }
691
692    /// Gets a mutable reference to a plugin by ID and version (parallel version).
693    ///
694    /// This method allows plugins to access other registered plugins for modification using parallel processing.
695    ///
696    /// # Parameters
697    ///
698    /// * `id` - Plugin identifier
699    /// * `version` - Plugin version
700    ///
701    /// # Returns
702    ///
703    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
704    pub fn par_get_plugin_mut(
705        &self,
706        id: &str,
707        version: &Version,
708    ) -> Option<&mut Plugin<'static, O, I>> {
709        self.loader.as_mut().par_get_plugin_mut(id, version)
710    }
711
712    /// Gets a mutable reference to a plugin by bundle.
713    ///
714    /// This method allows plugins to access other registered plugins for modification by bundle information.
715    ///
716    /// # Parameters
717    ///
718    /// * `bundle` - Plugin bundle information
719    ///
720    /// # Returns
721    ///
722    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
723    pub fn get_plugin_mut_by_bundle(&self, bundle: &Bundle) -> Option<&mut Plugin<'static, O, I>> {
724        self.loader.as_mut().get_plugin_mut_by_bundle(bundle)
725    }
726
727    /// Gets a mutable reference to a plugin by bundle (parallel version).
728    ///
729    /// This method allows plugins to access other registered plugins for modification by bundle information using parallel processing.
730    ///
731    /// # Parameters
732    ///
733    /// * `bundle` - Plugin bundle information
734    ///
735    /// # Returns
736    ///
737    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
738    pub fn par_get_plugin_mut_by_bundle(
739        &self,
740        bundle: &Bundle,
741    ) -> Option<&mut Plugin<'static, O, I>> {
742        self.loader.as_mut().par_get_plugin_mut_by_bundle(bundle)
743    }
744
745    /// Gets all plugins with the specified ID.
746    ///
747    /// This method allows plugins to access all versions of plugins with a specific ID.
748    ///
749    /// # Parameters
750    ///
751    /// * `id` - Plugin identifier to search for
752    ///
753    /// # Returns
754    ///
755    /// Returns `Vec<&Plugin<'static, O, I>>` containing all matching plugins.
756    pub fn get_plugins_by_id(&self, id: &str) -> Vec<&Plugin<'static, O, I>> {
757        self.loader.as_ref().get_plugins_by_id(id)
758    }
759
760    /// Gets all plugins with the specified ID (parallel version).
761    ///
762    /// This method allows plugins to access all versions of plugins with a specific ID using parallel processing.
763    ///
764    /// # Parameters
765    ///
766    /// * `id` - Plugin identifier to search for
767    ///
768    /// # Returns
769    ///
770    /// Returns `Vec<&Plugin<'static, O, I>>` containing all matching plugins.
771    pub fn par_get_plugins_by_id(&self, id: &str) -> Vec<&Plugin<'static, O, I>> {
772        self.loader.as_ref().par_get_plugins_by_id(id)
773    }
774
775    /// Gets mutable references to all plugins with the specified ID.
776    ///
777    /// This method allows plugins to access all versions of plugins with a specific ID for modification.
778    ///
779    /// # Parameters
780    ///
781    /// * `id` - Plugin identifier to search for
782    ///
783    /// # Returns
784    ///
785    /// Returns `Vec<&mut Plugin<'static, O, I>>` containing all matching plugins.
786    pub fn get_plugins_by_id_mut(&self, id: &str) -> Vec<&mut Plugin<'static, O, I>> {
787        self.loader.as_mut().get_plugins_by_id_mut(id)
788    }
789
790    /// Gets mutable references to all plugins with the specified ID (parallel version).
791    ///
792    /// This method allows plugins to access all versions of plugins with a specific ID for modification using parallel processing.
793    ///
794    /// # Parameters
795    ///
796    /// * `id` - Plugin identifier to search for
797    ///
798    /// # Returns
799    ///
800    /// Returns `Vec<&mut Plugin<'static, O, I>>` containing all matching plugins.
801    pub fn par_get_plugins_by_id_mut(&self, id: &str) -> Vec<&mut Plugin<'static, O, I>> {
802        self.loader.as_mut().par_get_plugins_by_id_mut(id)
803    }
804
805    /// Gets a reference to all loaded plugins.
806    ///
807    /// This method allows plugins to access the complete list of loaded plugins.
808    ///
809    /// # Returns
810    ///
811    /// Returns `&Vec<Plugin<'static, O, I>>` containing all loaded plugins.
812    pub fn get_plugins(&self) -> &Vec<Plugin<'static, O, I>> {
813        self.loader.as_ref().get_plugins()
814    }
815
816    /// Gets a reference to the function registry.
817    ///
818    /// This method allows plugins to access the registry of functions available to plugins.
819    ///
820    /// # Returns
821    ///
822    /// Returns `&Registry<O>` containing the function registry.
823    pub fn get_registry(&self) -> &Registry<O> {
824        self.loader.as_ref().get_registry()
825    }
826
827    /// Gets a reference to the function requests.
828    ///
829    /// This method allows plugins to access the collection of function requests.
830    ///
831    /// # Returns
832    ///
833    /// Returns `&Requests` containing the function requests.
834    pub fn get_requests(&self) -> &Requests {
835        self.loader.as_ref().get_requests()
836    }
837
838    /// Calls a function request across all eligible plugins.
839    ///
840    /// This method allows plugins to call a function request on all plugins that have the highest
841    /// version for their ID (to avoid calling multiple versions of the same plugin).
842    ///
843    /// # Parameters
844    ///
845    /// * `name` - Name of the function request to call
846    /// * `args` - Arguments to pass to the function
847    ///
848    /// # Returns
849    ///
850    /// Returns `Result<Vec<O>, PluginCallRequestError>` containing results from all
851    /// eligible plugins that have the requested function.
852    pub fn call_request(
853        &self,
854        name: &str,
855        args: &[Variable],
856    ) -> Result<Vec<O>, PluginCallRequestError> {
857        self.loader.as_ref().call_request(name, args)
858    }
859
860    /// Calls a function request across all eligible plugins (parallel version).
861    ///
862    /// This method allows plugins to call a function request on all plugins that have the highest
863    /// version for their ID using parallel processing.
864    ///
865    /// # Parameters
866    ///
867    /// * `name` - Name of the function request to call
868    /// * `args` - Arguments to pass to the function
869    ///
870    /// # Returns
871    ///
872    /// Returns `Result<Vec<O>, PluginCallRequestError>` containing results from all
873    /// eligible plugins that have the requested function.
874    pub fn par_call_request(
875        &self,
876        name: &str,
877        args: &[Variable],
878    ) -> Result<Vec<O>, PluginCallRequestError> {
879        self.loader.as_ref().par_call_request(name, args)
880    }
881
882    /// Calls a function on a required dependency.
883    ///
884    /// This method allows the current plugin to call functions exposed by its required dependencies.
885    /// It ensures that the dependency exists and is loaded before attempting the call.
886    ///
887    /// # Parameters
888    ///
889    /// * `id` - Dependency plugin ID
890    /// * `version` - Dependency plugin version
891    /// * `name` - Function name to call
892    /// * `args` - Arguments to pass to the function
893    ///
894    /// # Returns
895    ///
896    /// Returns `Result<O, CallFunctionDependError>` containing the function result on success,
897    /// or an error if the dependency is not found or the function call fails.
898    ///
899    /// # Note
900    ///
901    /// This method only works with required dependencies. For optional dependencies,
902    /// use `call_function_optional_depend`.
903    pub fn call_function_depend(
904        &self,
905        id: &str,
906        version: &Version,
907        name: &str,
908        args: &[Variable],
909    ) -> Result<O, CallFunctionDependError> {
910        let depend = self
911            .depends
912            .iter()
913            .find(|&depend| *depend == (id, version))
914            .ok_or(CallFunctionDependError::DependNotFound)?;
915
916        let plugin = self
917            .loader
918            .as_ref()
919            .get_plugin_by_bundle(depend)
920            .ok_or(CallFunctionDependError::DependNotFound)?;
921
922        Ok(plugin.call_function(name, args)?)
923    }
924
925    /// Calls a function on an optional dependency.
926    ///
927    /// This method allows the current plugin to call functions exposed by its optional dependencies.
928    /// Unlike required dependencies, this method returns `None` if the dependency is not available.
929    ///
930    /// # Parameters
931    ///
932    /// * `id` - Optional dependency plugin ID
933    /// * `version` - Optional dependency plugin version
934    /// * `name` - Function name to call
935    /// * `args` - Arguments to pass to the function
936    ///
937    /// # Returns
938    ///
939    /// Returns `Result<Option<O>, PluginCallFunctionError>` containing:
940    /// - `Ok(Some(result))` if the dependency exists and the call succeeds
941    /// - `Ok(None)` if the dependency is not available
942    /// - `Err(error)` if the function call fails
943    ///
944    /// # Note
945    ///
946    /// This method only works with optional dependencies. For required dependencies,
947    /// use `call_function_depend`.
948    pub fn call_function_optional_depend(
949        &self,
950        id: &str,
951        version: &Version,
952        name: &str,
953        args: &[Variable],
954    ) -> Result<Option<O>, PluginCallFunctionError> {
955        let depend = self
956            .optional_depends
957            .iter()
958            .find(|&depend| *depend == (id, version));
959
960        depend
961            .and_then(|depend| self.loader.as_ref().get_plugin_by_bundle(depend))
962            .map(|plugin| plugin.call_function(name, args))
963            .transpose()
964    }
965}