plux_rs/context/load_plugin_context.rs
1use crate::{Info, Plugin, Requests, function::Function, utils::RegisterRequestError};
2
3/// Context provided during plugin loading.
4///
5/// LoadPluginContext gives plugin managers access to the plugin being loaded and
6/// the system's function requests. It allows managers to register plugin functions
7/// and validate them against the expected interface.
8///
9/// # Type Parameters
10///
11/// * `'a` - Lifetime for references within the plugin
12/// * `'b` - Lifetime of the context references
13/// * `O` - Output type for plugin functions (must implement Send + Sync)
14/// * `I` - Plugin information type (must implement Info trait)
15///
16/// # Fields
17///
18/// * `plugin` - Mutable reference to the plugin being loaded
19/// * `requests` - Reference to the system's function requests
20///
21/// # Example
22///
23/// ```rust,no_run
24/// use plux_rs::{Manager, utils::ManagerResult, LoadPluginContext, RegisterPluginContext, Api, StdInfo};
25///
26/// struct MyManager;
27///
28/// impl Manager<'_, (), StdInfo> for MyManager {
29/// fn format(&self) -> &'static str { "my" }
30///
31/// fn register_plugin(&mut self, _context: RegisterPluginContext) -> ManagerResult<StdInfo> {
32/// Ok(StdInfo::new())
33/// }
34///
35/// fn load_plugin(
36/// &mut self,
37/// context: LoadPluginContext<'_, '_, (), StdInfo>,
38/// api: Api<(), StdInfo>
39/// ) -> ManagerResult<()> {
40/// // Register plugin functions that match the requests
41/// for request in context.requests() {
42/// // Register corresponding function in the plugin
43/// }
44/// Ok(())
45/// }
46/// }
47/// ```
48pub struct LoadPluginContext<'a, 'b, O: Send + Sync, I: Info> {
49 plugin: &'b mut Plugin<'a, O, I>,
50 requests: &'b Requests,
51}
52
53impl<'a, 'b, O: Send + Sync, I: Info> LoadPluginContext<'a, 'b, O, I> {
54 /// Creates a new load plugin context.
55 ///
56 /// This is an internal constructor used by the loader when loading plugins.
57 ///
58 /// # Parameters
59 ///
60 /// * `plugin` - Mutable reference to the plugin being loaded
61 /// * `requests` - Reference to the system's function requests
62 ///
63 /// # Returns
64 ///
65 /// Returns a new LoadPluginContext instance.
66 pub(crate) fn new(plugin: &'b mut Plugin<'a, O, I>, requests: &'b Requests) -> Self {
67 Self { plugin, requests }
68 }
69
70 /// Gets a reference to the plugin being loaded.
71 ///
72 /// # Returns
73 ///
74 /// Returns an immutable reference to the plugin.
75 pub const fn plugin(&'b self) -> &'b Plugin<'a, O, I> {
76 self.plugin
77 }
78
79 /// Gets a reference to the system's function requests.
80 ///
81 /// # Returns
82 ///
83 /// Returns a reference to the requests that plugins should implement.
84 pub const fn requests(&self) -> &'b Requests {
85 self.requests
86 }
87
88 /// Registers a function that implements a system request.
89 ///
90 /// This method validates that the provided function matches the signature of
91 /// a registered system request and then registers it with the plugin.
92 ///
93 /// # Parameters
94 ///
95 /// * `request` - The function that implements a system request
96 ///
97 /// # Returns
98 ///
99 /// Returns `Result<(), RegisterRequestError>` indicating success or failure.
100 /// Fails if the function doesn't match any registered request or has incorrect arguments.
101 ///
102 /// # Type Parameters
103 ///
104 /// * `F` - Type of the function (must implement Function trait)
105 pub fn register_request<F>(&mut self, request: F) -> Result<(), RegisterRequestError>
106 where
107 F: Function<Output = O> + 'static,
108 {
109 if let Some(req) = self.requests.iter().find(|req| *req.name == request.name()) {
110 for input in req.inputs.iter() {
111 request
112 .inputs()
113 .iter()
114 .find(|arg| *input == arg.ty)
115 .ok_or(RegisterRequestError::ArgumentsIncorrectly)?;
116 }
117
118 if req.output != request.output().map(|arg| arg.ty) {
119 return Err(RegisterRequestError::ArgumentsIncorrectly);
120 }
121 } else {
122 return Err(RegisterRequestError::NotFound);
123 }
124
125 self.plugin.requests.push(Box::new(request));
126
127 Ok(())
128 }
129}