Skip to main content

r2x_python/
plugin_invoker.rs

1//! Plugin invocation and execution
2
3use crate::errors::BridgeError;
4use r2x_logger as logger;
5use r2x_manifest::{
6    runtime::{build_runtime_bindings, RuntimeBindings},
7    PluginKind, PluginSpec,
8};
9use std::time::Duration;
10
11/// Timings for a plugin invocation phase
12pub struct PluginInvocationTimings {
13    pub python_invocation: Duration,
14    pub serialization: Duration,
15}
16
17/// Result of running a plugin through the Python bridge
18pub struct PluginInvocationResult {
19    /// JSON text emitted by the plugin (may be `"null"`)
20    pub output: String,
21    /// Optional per-phase timings for diagnostics
22    pub timings: Option<PluginInvocationTimings>,
23}
24
25impl super::Bridge {
26    pub fn invoke_plugin(
27        &self,
28        target: &str,
29        config_json: &str,
30        stdin_json: Option<&str>,
31        plugin_metadata: Option<&PluginSpec>,
32    ) -> Result<PluginInvocationResult, BridgeError> {
33        let runtime_bindings = plugin_metadata.map(build_runtime_bindings);
34
35        if let Some(plugin) = plugin_metadata {
36            if plugin.kind == PluginKind::Upgrader {
37                logger::debug("Routing to upgrader plugin handler");
38                return self.invoke_upgrader_plugin(
39                    target,
40                    config_json,
41                    runtime_bindings.as_ref(),
42                    plugin_metadata,
43                );
44            }
45        }
46
47        self.invoke_plugin_regular(target, config_json, stdin_json, runtime_bindings.as_ref())
48    }
49
50    pub fn invoke_plugin_with_bindings(
51        &self,
52        target: &str,
53        config_json: &str,
54        stdin_json: Option<&str>,
55        runtime_bindings: Option<&RuntimeBindings>,
56    ) -> Result<PluginInvocationResult, BridgeError> {
57        if let Some(bindings) = runtime_bindings {
58            if bindings.plugin_kind == PluginKind::Upgrader {
59                logger::debug("Routing to upgrader plugin handler (runtime bindings)");
60                return self.invoke_upgrader_plugin(target, config_json, Some(bindings), None);
61            }
62        }
63
64        self.invoke_plugin_regular(target, config_json, stdin_json, runtime_bindings)
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn plugin_invocation_result_basics() {
74        let result = PluginInvocationResult {
75            output: String::new(),
76            timings: None,
77        };
78        assert!(result.output.is_empty());
79    }
80}