cardinal_wasm_plugins/
instance.rs

1use crate::host::make_imports;
2use crate::plugin::WasmPlugin;
3use crate::runner::{ExecutionType, HostFunctionMap};
4use crate::{ExecutionContext, ExecutionRequest, ExecutionResponse};
5use cardinal_errors::internal::CardinalInternalError;
6use cardinal_errors::CardinalError;
7use wasmer::{FunctionEnv, Instance, Memory, Store};
8
9pub struct WasmInstance {
10    pub store: Store,
11    pub instance: Instance,
12    pub memory: Memory,
13    pub env: FunctionEnv<ExecutionContext>, // <— store the env here
14}
15
16impl WasmInstance {
17    pub fn from_plugin(
18        plugin: &WasmPlugin,
19        exec_type: ExecutionType,
20        host_imports: Option<&HostFunctionMap>,
21    ) -> Result<Self, CardinalError> {
22        let mut store = Store::new(plugin.engine.clone());
23
24        let ctx = match exec_type {
25            ExecutionType::Inbound => ExecutionContext::Inbound(ExecutionRequest {
26                memory: None,
27                req_headers: Default::default(),
28                query: Default::default(),
29                body: None,
30            }),
31            ExecutionType::Outbound => ExecutionContext::Outbound(ExecutionResponse {
32                memory: None,
33                req_headers: Default::default(),
34                query: Default::default(),
35                resp_headers: Default::default(),
36                status: 200,
37                body: None,
38            }),
39        };
40
41        let env = FunctionEnv::new(&mut store, ctx);
42
43        let imports = make_imports(&mut store, &env, exec_type, host_imports);
44
45        // Create the instance.
46        let instance = Instance::new(&mut store, &plugin.module, &imports).map_err(|e| {
47            CardinalError::InternalError(CardinalInternalError::InvalidWasmModule(format!(
48                "Error creating WASM Instance {e}"
49            )))
50        })?;
51
52        // Stash it in the env so host imports can access it.
53        // Get the guest linear memory (usually named "memory")
54        let memory_name = plugin.memory_name.as_str(); // or default to "memory"
55        let memory = instance
56            .exports
57            .get_memory(memory_name)
58            .map_err(|e| {
59                CardinalError::InternalError(CardinalInternalError::InvalidWasmModule(format!(
60                    "missing memory export `{memory_name}`: {e}"
61                )))
62            })?
63            .clone();
64
65        env.as_mut(&mut store).replace_memory(memory.clone());
66
67        Ok(WasmInstance {
68            store,
69            instance,
70            memory,
71            env,
72        })
73    }
74}