use postcard::to_stdvec;
use reifydb_core::value::column::columns::Columns;
use reifydb_routine::procedure::{Procedure, context::ProcedureContext, error::ProcedureError};
use reifydb_sdk::{error::FFIError, marshal::wasm::unmarshal_columns_from_bytes};
use reifydb_transaction::transaction::Transaction;
use reifydb_type::error::Error;
use crate::{error::ExtensionError, loader::wasm::invoke_wasm_module};
fn ext_err(err: ExtensionError) -> ProcedureError {
ProcedureError::Wrapped(Box::new(Error::from(FFIError::Other(err.to_string()))))
}
pub struct WasmProcedure {
name: String,
wasm_bytes: Vec<u8>,
}
impl WasmProcedure {
pub fn new(name: impl Into<String>, wasm_bytes: Vec<u8>) -> Self {
Self {
name: name.into(),
wasm_bytes,
}
}
pub fn name(&self) -> &str {
&self.name
}
}
unsafe impl Send for WasmProcedure {}
unsafe impl Sync for WasmProcedure {}
impl Procedure for WasmProcedure {
fn call(&self, ctx: &ProcedureContext, _tx: &mut Transaction<'_>) -> Result<Columns, ProcedureError> {
let params_bytes = to_stdvec(ctx.params).map_err(|e| {
ext_err(ExtensionError::Invocation(format!(
"WASM procedure '{}' failed to serialize params: {}",
self.name, e
)))
})?;
let label = format!("WASM procedure '{}'", self.name);
let output_bytes =
invoke_wasm_module(&self.wasm_bytes, "procedure", ¶ms_bytes, &label).map_err(ext_err)?;
Ok(unmarshal_columns_from_bytes(&output_bytes))
}
}