extism_runtime/
plugin_ref.rs

1use crate::*;
2
3// PluginRef is used to access a plugin from a context-scoped plugin registry
4pub struct PluginRef<'a> {
5    pub id: PluginIndex,
6    running: bool,
7    pub(crate) epoch_timer_tx: std::sync::mpsc::SyncSender<TimerAction>,
8    plugin: *mut Plugin,
9    _t: std::marker::PhantomData<&'a ()>,
10}
11
12impl<'a> PluginRef<'a> {
13    /// Initialize the plugin for a new call
14    pub(crate) fn start_call(mut self, is_start: bool) -> Self {
15        trace!("PluginRef::start_call: {}", self.id,);
16
17        let plugin = unsafe { &mut *self.plugin };
18        if is_start {
19            if let Err(e) = plugin.reset_store() {
20                error!("Call to Plugin::reset_store failed: {e:?}");
21            }
22        }
23
24        if plugin.instance.is_none() {
25            trace!("Plugin::instance is none, instantiating");
26            if let Err(e) = plugin.instantiate() {
27                error!("Plugin::instantiate failed: {e:?}");
28                plugin.error(e, ());
29            }
30        }
31
32        self.running = true;
33        self
34    }
35
36    /// Create a `PluginRef` from a context
37    ///
38    /// - Reinstantiates the plugin if `should_reinstantiate` is set to `true` and WASI is enabled
39    pub fn new(ctx: &'a mut Context, plugin_id: PluginIndex, clear_error: bool) -> Option<Self> {
40        trace!("Loading plugin {plugin_id}");
41
42        let epoch_timer_tx = ctx.epoch_timer_tx.clone();
43
44        let plugin = if let Some(plugin) = ctx.plugin(plugin_id) {
45            plugin
46        } else {
47            error!("Plugin does not exist: {plugin_id}");
48            return ctx.error(format!("Plugin does not exist: {plugin_id}"), None);
49        };
50
51        let plugin = unsafe { &mut *plugin };
52
53        if clear_error {
54            trace!("Clearing context error");
55            ctx.error = None;
56            trace!("Clearing plugin error: {plugin_id}");
57            plugin.clear_error();
58        }
59
60        Some(PluginRef {
61            id: plugin_id,
62            plugin,
63            epoch_timer_tx,
64            _t: std::marker::PhantomData,
65            running: false,
66        })
67    }
68}
69
70impl<'a> AsRef<Plugin> for PluginRef<'a> {
71    fn as_ref(&self) -> &Plugin {
72        unsafe { &*self.plugin }
73    }
74}
75
76impl<'a> AsMut<Plugin> for PluginRef<'a> {
77    fn as_mut(&mut self) -> &mut Plugin {
78        unsafe { &mut *self.plugin }
79    }
80}
81
82impl<'a> Drop for PluginRef<'a> {
83    fn drop(&mut self) {
84        trace!("Dropping PluginRef {}", self.id);
85        if self.running {
86            let plugin = self.as_mut();
87
88            // Stop timer
89            if let Err(e) = plugin.stop_timer() {
90                let id = plugin.timer_id;
91                error!("Failed to stop timeout manager for {id}: {e:?}");
92            }
93        }
94    }
95}