cardinal_wasm_plugins/
runner.rs1use crate::host::{HostFunctionBuilder, HostImportHandle};
2use crate::instance::InstancePool;
3use crate::plugin::WasmPlugin;
4use crate::SharedExecutionContext;
5use cardinal_errors::CardinalError;
6use std::sync::Arc;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ExecutionPhase {
10 Inbound,
11 Outbound,
12}
13
14#[derive(Debug)]
15pub struct ExecutionResult {
16 pub should_continue: bool,
17 pub execution_context: SharedExecutionContext,
18}
19
20pub struct WasmRunner {
21 pool: Arc<InstancePool>,
22}
23
24impl WasmRunner {
25 pub fn new(
26 plugin: &Arc<WasmPlugin>,
27 phase: ExecutionPhase,
28 host_imports: Option<&[HostImportHandle]>,
29 ) -> Self {
30 let dynamic = host_imports
31 .map(|imports| imports.to_vec())
32 .unwrap_or_default();
33
34 let pool = InstancePool::new(plugin.clone(), phase, dynamic);
35 Self {
36 pool: Arc::new(pool),
37 }
38 }
39
40 pub fn run_raw(
41 &self,
42 shared_ctx: SharedExecutionContext,
43 ) -> Result<ExecutionResult, CardinalError> {
44 let mut guard = self.pool.acquire(shared_ctx.clone())?;
45 let instance = guard.instance();
46
47 let body = shared_ctx.read().request().body().cloned();
48 let body_slice = body.as_ref().map(|bytes| bytes.as_ref());
49
50 let (ptr, len) = instance.write_body(body_slice)?;
51 let decision = instance.call_handle(ptr, len)?;
52
53 Ok(ExecutionResult {
54 should_continue: decision == 1,
55 execution_context: shared_ctx,
56 })
57 }
58
59 pub fn run(
60 &self,
61 shared_ctx: SharedExecutionContext,
62 ) -> Result<ExecutionResult, CardinalError> {
63 let run = self.run_raw(shared_ctx);
64 match run {
65 Ok(result) => Ok(result),
66 Err(e) => {
67 tracing::error!("Failed to run plugin: {}", e);
68 Err(e)
69 }
70 }
71 }
72}
73
74pub fn host_import_from_builder<N, S>(
75 namespace: N,
76 name: S,
77 builder: HostFunctionBuilder,
78) -> HostImportHandle
79where
80 N: Into<String>,
81 S: Into<String>,
82{
83 Arc::new(crate::host::DynamicHostImport::new(
84 namespace, name, builder,
85 ))
86}