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        Ptr, RegisterManagerError, RegisterPluginError, UnloadPluginError, UnregisterManagerError,
9        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, (Option<RegisterPluginError>, Option<LoadPluginError>)>`
439    /// containing the plugin bundle on success, or errors from registration or loading.
440    pub fn load_plugin_now(
441        &self,
442        path: &str,
443    ) -> Result<Bundle, (Option<RegisterPluginError>, Option<LoadPluginError>)> {
444        self.loader.as_mut().load_plugin_now(path)
445    }
446
447    /// Loads multiple plugins from the specified paths.
448    ///
449    /// This method allows plugins to register and load multiple plugins in sequence.
450    ///
451    /// # Parameters
452    ///
453    /// * `paths` - Iterator of paths to plugin files or directories
454    ///
455    /// # Returns
456    ///
457    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>`
458    /// containing the plugin bundles on success, or errors from registration or loading.
459    ///
460    /// # Type Parameters
461    ///
462    /// * `'b` - Lifetime of the path references
463    /// * `P` - Type of the iterator containing path references
464    pub fn load_plugins<'b, P>(
465        &self,
466        paths: P,
467    ) -> Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>
468    where
469        P: IntoIterator<Item = &'b str>,
470    {
471        self.loader.as_mut().load_plugins(paths)
472    }
473
474    /// Loads multiple plugins from the specified paths (parallel version).
475    ///
476    /// This method allows plugins to register and load multiple plugins concurrently.
477    ///
478    /// # Parameters
479    ///
480    /// * `paths` - Parallel iterator of paths to plugin files or directories
481    ///
482    /// # Returns
483    ///
484    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>`
485    /// containing the plugin bundles on success, or errors from registration or loading.
486    ///
487    /// # Type Parameters
488    ///
489    /// * `'b` - Lifetime of the path references
490    /// * `P` - Type of the parallel iterator containing path references
491    pub fn par_load_plugins<'b, P>(
492        &self,
493        paths: P,
494    ) -> Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<LoadPluginError>)>
495    where
496        P: IntoParallelIterator<Item = &'b str>,
497    {
498        self.loader.as_mut().par_load_plugins(paths)
499    }
500
501    /// Loads only the plugins that are used (not dependencies of other plugins).
502    ///
503    /// This method allows plugins to register and load only the plugins that are not
504    /// dependencies of other plugins, and automatically unregisters unused plugins.
505    ///
506    /// # Parameters
507    ///
508    /// * `paths` - Iterator of paths to plugin files or directories
509    ///
510    /// # Returns
511    ///
512    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<UnregisterPluginError>, Option<LoadPluginError>)>`
513    /// containing the plugin bundles on success, or errors from registration, unregistration, or loading.
514    ///
515    /// # Type Parameters
516    ///
517    /// * `'b` - Lifetime of the path references
518    /// * `P` - Type of the iterator containing path references
519    pub fn load_only_used_plugins<'b, P>(
520        &self,
521        paths: P,
522    ) -> Result<
523        Vec<Bundle>,
524        (
525            Option<RegisterPluginError>,
526            Option<UnregisterPluginError>,
527            Option<LoadPluginError>,
528        ),
529    >
530    where
531        P: IntoIterator<Item = &'b str>,
532    {
533        self.loader.as_mut().load_only_used_plugins(paths)
534    }
535
536    /// Loads only the plugins that are used (not dependencies of other plugins) (parallel version).
537    ///
538    /// This method allows plugins to register and load only the plugins that are not
539    /// dependencies of other plugins using parallel processing, and automatically unregisters unused plugins.
540    ///
541    /// # Parameters
542    ///
543    /// * `paths` - Parallel iterator of paths to plugin files or directories
544    ///
545    /// # Returns
546    ///
547    /// Returns `Result<Vec<Bundle>, (Option<RegisterPluginError>, Option<UnregisterPluginError>, Option<LoadPluginError>)>`
548    /// containing the plugin bundles on success, or errors from registration, unregistration, or loading.
549    ///
550    /// # Type Parameters
551    ///
552    /// * `'b` - Lifetime of the path references
553    /// * `P` - Type of the parallel iterator containing path references
554    pub fn par_load_only_used_plugins<'b, P>(
555        &self,
556        paths: P,
557    ) -> Result<
558        Vec<Bundle>,
559        (
560            Option<RegisterPluginError>,
561            Option<UnregisterPluginError>,
562            Option<LoadPluginError>,
563        ),
564    >
565    where
566        P: IntoParallelIterator<Item = &'b str>,
567    {
568        self.loader.as_mut().par_load_only_used_plugins(paths)
569    }
570
571    /// Unloads a plugin from the execution environment.
572    ///
573    /// This method allows plugins to unload other plugins by ID and version.
574    ///
575    /// # Parameters
576    ///
577    /// * `id` - Plugin identifier
578    /// * `version` - Plugin version
579    ///
580    /// # Returns
581    ///
582    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
583    pub fn unload_plugin(&self, id: &str, version: &Version) -> Result<(), UnloadPluginError> {
584        self.loader.as_mut().unload_plugin(id, version)
585    }
586
587    /// Unloads a plugin from the execution environment (parallel version).
588    ///
589    /// This method allows plugins to unload other plugins by ID and version using parallel processing.
590    ///
591    /// # Parameters
592    ///
593    /// * `id` - Plugin identifier
594    /// * `version` - Plugin version
595    ///
596    /// # Returns
597    ///
598    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
599    pub fn par_unload_plugin(&self, id: &str, version: &Version) -> Result<(), UnloadPluginError> {
600        self.loader.as_mut().par_unload_plugin(id, version)
601    }
602
603    /// Unloads a plugin from the execution environment by bundle.
604    ///
605    /// This method allows plugins to unload other plugins by bundle information.
606    ///
607    /// # Parameters
608    ///
609    /// * `bundle` - Plugin bundle information
610    ///
611    /// # Returns
612    ///
613    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
614    pub fn unload_plugin_by_bundle(&self, bundle: &Bundle) -> Result<(), UnloadPluginError> {
615        self.loader.as_mut().unload_plugin_by_bundle(bundle)
616    }
617
618    /// Unloads a plugin from the execution environment by bundle (parallel version).
619    ///
620    /// This method allows plugins to unload other plugins by bundle information using parallel processing.
621    ///
622    /// # Parameters
623    ///
624    /// * `bundle` - Plugin bundle information
625    ///
626    /// # Returns
627    ///
628    /// Returns `Result<(), UnloadPluginError>` indicating success or failure.
629    pub fn par_unload_plugin_by_bundle(&self, bundle: &Bundle) -> Result<(), UnloadPluginError> {
630        self.loader.as_mut().par_unload_plugin_by_bundle(bundle)
631    }
632
633    /// Gets an immutable reference to a plugin by ID and version.
634    ///
635    /// This method allows plugins to access other registered plugins.
636    ///
637    /// # Parameters
638    ///
639    /// * `id` - Plugin identifier
640    /// * `version` - Plugin version
641    ///
642    /// # Returns
643    ///
644    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
645    pub fn get_plugin(&self, id: &str, version: &Version) -> Option<&Plugin<'static, O, I>> {
646        self.loader.as_ref().get_plugin(id, version)
647    }
648
649    /// Gets an immutable reference to a plugin by ID and version (parallel version).
650    ///
651    /// This method allows plugins to access other registered plugins using parallel processing.
652    ///
653    /// # Parameters
654    ///
655    /// * `id` - Plugin identifier
656    /// * `version` - Plugin version
657    ///
658    /// # Returns
659    ///
660    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
661    pub fn par_get_plugin(&self, id: &str, version: &Version) -> Option<&Plugin<'static, O, I>> {
662        self.loader.as_ref().par_get_plugin(id, version)
663    }
664
665    /// Gets an immutable reference to a plugin by bundle.
666    ///
667    /// This method allows plugins to access other registered plugins by bundle information.
668    ///
669    /// # Parameters
670    ///
671    /// * `bundle` - Plugin bundle information
672    ///
673    /// # Returns
674    ///
675    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
676    pub fn get_plugin_by_bundle(&self, bundle: &Bundle) -> Option<&Plugin<'static, O, I>> {
677        self.loader.as_ref().get_plugin_by_bundle(bundle)
678    }
679
680    /// Gets an immutable reference to a plugin by bundle (parallel version).
681    ///
682    /// This method allows plugins to access other registered plugins by bundle information using parallel processing.
683    ///
684    /// # Parameters
685    ///
686    /// * `bundle` - Plugin bundle information
687    ///
688    /// # Returns
689    ///
690    /// Returns `Option<&Plugin<'static, O, I>>` containing the plugin if found.
691    pub fn par_get_plugin_by_bundle(&self, bundle: &Bundle) -> Option<&Plugin<'static, O, I>> {
692        self.loader.as_ref().par_get_plugin_by_bundle(bundle)
693    }
694
695    /// Gets a mutable reference to a plugin by ID and version.
696    ///
697    /// This method allows plugins to access other registered plugins for modification.
698    ///
699    /// # Parameters
700    ///
701    /// * `id` - Plugin identifier
702    /// * `version` - Plugin version
703    ///
704    /// # Returns
705    ///
706    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
707    pub fn get_plugin_mut(
708        &self,
709        id: &str,
710        version: &Version,
711    ) -> Option<&mut Plugin<'static, O, I>> {
712        self.loader.as_mut().get_plugin_mut(id, version)
713    }
714
715    /// Gets a mutable reference to a plugin by ID and version (parallel version).
716    ///
717    /// This method allows plugins to access other registered plugins for modification using parallel processing.
718    ///
719    /// # Parameters
720    ///
721    /// * `id` - Plugin identifier
722    /// * `version` - Plugin version
723    ///
724    /// # Returns
725    ///
726    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
727    pub fn par_get_plugin_mut(
728        &self,
729        id: &str,
730        version: &Version,
731    ) -> Option<&mut Plugin<'static, O, I>> {
732        self.loader.as_mut().par_get_plugin_mut(id, version)
733    }
734
735    /// Gets a mutable reference to a plugin by bundle.
736    ///
737    /// This method allows plugins to access other registered plugins for modification by bundle information.
738    ///
739    /// # Parameters
740    ///
741    /// * `bundle` - Plugin bundle information
742    ///
743    /// # Returns
744    ///
745    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
746    pub fn get_plugin_mut_by_bundle(&self, bundle: &Bundle) -> Option<&mut Plugin<'static, O, I>> {
747        self.loader.as_mut().get_plugin_mut_by_bundle(bundle)
748    }
749
750    /// Gets a mutable reference to a plugin by bundle (parallel version).
751    ///
752    /// This method allows plugins to access other registered plugins for modification by bundle information using parallel processing.
753    ///
754    /// # Parameters
755    ///
756    /// * `bundle` - Plugin bundle information
757    ///
758    /// # Returns
759    ///
760    /// Returns `Option<&mut Plugin<'static, O, I>>` containing the plugin if found.
761    pub fn par_get_plugin_mut_by_bundle(
762        &self,
763        bundle: &Bundle,
764    ) -> Option<&mut Plugin<'static, O, I>> {
765        self.loader.as_mut().par_get_plugin_mut_by_bundle(bundle)
766    }
767
768    /// Gets all plugins with the specified ID.
769    ///
770    /// This method allows plugins to access all versions of plugins with a specific ID.
771    ///
772    /// # Parameters
773    ///
774    /// * `id` - Plugin identifier to search for
775    ///
776    /// # Returns
777    ///
778    /// Returns `Vec<&Plugin<'static, O, I>>` containing all matching plugins.
779    pub fn get_plugins_by_id(&self, id: &str) -> Vec<&Plugin<'static, O, I>> {
780        self.loader.as_ref().get_plugins_by_id(id)
781    }
782
783    /// Gets all plugins with the specified ID (parallel version).
784    ///
785    /// This method allows plugins to access all versions of plugins with a specific ID using parallel processing.
786    ///
787    /// # Parameters
788    ///
789    /// * `id` - Plugin identifier to search for
790    ///
791    /// # Returns
792    ///
793    /// Returns `Vec<&Plugin<'static, O, I>>` containing all matching plugins.
794    pub fn par_get_plugins_by_id(&self, id: &str) -> Vec<&Plugin<'static, O, I>> {
795        self.loader.as_ref().par_get_plugins_by_id(id)
796    }
797
798    /// Gets mutable references to all plugins with the specified ID.
799    ///
800    /// This method allows plugins to access all versions of plugins with a specific ID for modification.
801    ///
802    /// # Parameters
803    ///
804    /// * `id` - Plugin identifier to search for
805    ///
806    /// # Returns
807    ///
808    /// Returns `Vec<&mut Plugin<'static, O, I>>` containing all matching plugins.
809    pub fn get_plugins_by_id_mut(&self, id: &str) -> Vec<&mut Plugin<'static, O, I>> {
810        self.loader.as_mut().get_plugins_by_id_mut(id)
811    }
812
813    /// Gets mutable references to all plugins with the specified ID (parallel version).
814    ///
815    /// This method allows plugins to access all versions of plugins with a specific ID for modification using parallel processing.
816    ///
817    /// # Parameters
818    ///
819    /// * `id` - Plugin identifier to search for
820    ///
821    /// # Returns
822    ///
823    /// Returns `Vec<&mut Plugin<'static, O, I>>` containing all matching plugins.
824    pub fn par_get_plugins_by_id_mut(&self, id: &str) -> Vec<&mut Plugin<'static, O, I>> {
825        self.loader.as_mut().par_get_plugins_by_id_mut(id)
826    }
827
828    /// Gets a reference to all loaded plugins.
829    ///
830    /// This method allows plugins to access the complete list of loaded plugins.
831    ///
832    /// # Returns
833    ///
834    /// Returns `&Vec<Plugin<'static, O, I>>` containing all loaded plugins.
835    pub fn get_plugins(&self) -> &Vec<Plugin<'static, O, I>> {
836        self.loader.as_ref().get_plugins()
837    }
838
839    /// Gets a reference to the function registry.
840    ///
841    /// This method allows plugins to access the registry of functions available to plugins.
842    ///
843    /// # Returns
844    ///
845    /// Returns `&Registry<O>` containing the function registry.
846    pub fn get_registry(&self) -> &Registry<O> {
847        self.loader.as_ref().get_registry()
848    }
849
850    /// Gets a reference to the function requests.
851    ///
852    /// This method allows plugins to access the collection of function requests.
853    ///
854    /// # Returns
855    ///
856    /// Returns `&Requests` containing the function requests.
857    pub fn get_requests(&self) -> &Requests {
858        self.loader.as_ref().get_requests()
859    }
860
861    /// Calls a function request across all eligible plugins.
862    ///
863    /// This method allows plugins to call a function request on all plugins that have the highest
864    /// version for their ID (to avoid calling multiple versions of the same plugin).
865    ///
866    /// # Parameters
867    ///
868    /// * `name` - Name of the function request to call
869    /// * `args` - Arguments to pass to the function
870    ///
871    /// # Returns
872    ///
873    /// Returns `Result<Vec<O>, PluginCallRequestError>` containing results from all
874    /// eligible plugins that have the requested function.
875    pub fn call_request(
876        &self,
877        name: &str,
878        args: &[Variable],
879    ) -> Result<Vec<O>, PluginCallRequestError> {
880        self.loader.as_ref().call_request(name, args)
881    }
882
883    /// Calls a function request across all eligible plugins (parallel version).
884    ///
885    /// This method allows plugins to call a function request on all plugins that have the highest
886    /// version for their ID using parallel processing.
887    ///
888    /// # Parameters
889    ///
890    /// * `name` - Name of the function request to call
891    /// * `args` - Arguments to pass to the function
892    ///
893    /// # Returns
894    ///
895    /// Returns `Result<Vec<O>, PluginCallRequestError>` containing results from all
896    /// eligible plugins that have the requested function.
897    pub fn par_call_request(
898        &self,
899        name: &str,
900        args: &[Variable],
901    ) -> Result<Vec<O>, PluginCallRequestError> {
902        self.loader.as_ref().par_call_request(name, args)
903    }
904
905    /// Calls a function on a required dependency.
906    ///
907    /// This method allows the current plugin to call functions exposed by its required dependencies.
908    /// It ensures that the dependency exists and is loaded before attempting the call.
909    ///
910    /// # Parameters
911    ///
912    /// * `id` - Dependency plugin ID
913    /// * `version` - Dependency plugin version
914    /// * `name` - Function name to call
915    /// * `args` - Arguments to pass to the function
916    ///
917    /// # Returns
918    ///
919    /// Returns `Result<O, CallFunctionDependError>` containing the function result on success,
920    /// or an error if the dependency is not found or the function call fails.
921    ///
922    /// # Note
923    ///
924    /// This method only works with required dependencies. For optional dependencies,
925    /// use `call_function_optional_depend`.
926    pub fn call_function_depend(
927        &self,
928        id: &str,
929        version: &Version,
930        name: &str,
931        args: &[Variable],
932    ) -> Result<O, CallFunctionDependError> {
933        let depend = self
934            .depends
935            .iter()
936            .find(|&depend| *depend == (id, version))
937            .ok_or(CallFunctionDependError::DependNotFound)?;
938
939        let plugin = self
940            .loader
941            .as_ref()
942            .get_plugin_by_bundle(depend)
943            .ok_or(CallFunctionDependError::DependNotFound)?;
944
945        Ok(plugin.call_function(name, args)?)
946    }
947
948    /// Calls a function on an optional dependency.
949    ///
950    /// This method allows the current plugin to call functions exposed by its optional dependencies.
951    /// Unlike required dependencies, this method returns `None` if the dependency is not available.
952    ///
953    /// # Parameters
954    ///
955    /// * `id` - Optional dependency plugin ID
956    /// * `version` - Optional dependency plugin version
957    /// * `name` - Function name to call
958    /// * `args` - Arguments to pass to the function
959    ///
960    /// # Returns
961    ///
962    /// Returns `Result<Option<O>, PluginCallFunctionError>` containing:
963    /// - `Ok(Some(result))` if the dependency exists and the call succeeds
964    /// - `Ok(None)` if the dependency is not available
965    /// - `Err(error)` if the function call fails
966    ///
967    /// # Note
968    ///
969    /// This method only works with optional dependencies. For required dependencies,
970    /// use `call_function_depend`.
971    pub fn call_function_optional_depend(
972        &self,
973        id: &str,
974        version: &Version,
975        name: &str,
976        args: &[Variable],
977    ) -> Result<Option<O>, PluginCallFunctionError> {
978        let depend = self
979            .optional_depends
980            .iter()
981            .find(|&depend| *depend == (id, version));
982
983        depend
984            .and_then(|depend| self.loader.as_ref().get_plugin_by_bundle(depend))
985            .map(|plugin| plugin.call_function(name, args))
986            .transpose()
987    }
988}