mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 00:02:18 +00:00
* feat: custom node * add zen template, expose $nodes and $root * add custom handler to go and nodejs * add support for python, improve bindings, add error to zen template * fix: correct binding exports for nodejs and python * fix benchmark * improve rust api, trim template in zen templates * update cargo action * update expression version * compile action * fix action format
66 lines
1.8 KiB
Rust
66 lines
1.8 KiB
Rust
use std::ffi::{c_char, CStr, CString};
|
|
|
|
use anyhow::anyhow;
|
|
|
|
use zen_engine::handler::custom_node_adapter::{
|
|
CustomNodeAdapter, CustomNodeRequest, NoopCustomNode,
|
|
};
|
|
use zen_engine::handler::node::{NodeResponse, NodeResult};
|
|
|
|
use crate::languages::native::NativeCustomNode;
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum DynamicCustomNode {
|
|
Noop(NoopCustomNode),
|
|
Native(NativeCustomNode),
|
|
#[cfg(feature = "go")]
|
|
Go(crate::languages::go::GoCustomNode),
|
|
}
|
|
|
|
impl Default for DynamicCustomNode {
|
|
fn default() -> Self {
|
|
Self::Noop(Default::default())
|
|
}
|
|
}
|
|
|
|
impl CustomNodeAdapter for DynamicCustomNode {
|
|
async fn handle(&self, request: CustomNodeRequest<'_>) -> NodeResult {
|
|
match self {
|
|
DynamicCustomNode::Noop(cn) => cn.handle(request).await,
|
|
DynamicCustomNode::Native(cn) => cn.handle(request).await,
|
|
#[cfg(feature = "go")]
|
|
DynamicCustomNode::Go(cn) => cn.handle(request).await,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct ZenCustomNodeResult {
|
|
content: *const c_char,
|
|
error: *mut c_char,
|
|
}
|
|
|
|
impl ZenCustomNodeResult {
|
|
pub fn into_node_result(self) -> NodeResult {
|
|
let maybe_error = match self.error.is_null() {
|
|
false => Some(unsafe { CString::from_raw(self.error) }),
|
|
true => None,
|
|
};
|
|
|
|
if let Some(c_error) = maybe_error {
|
|
let maybe_str = c_error.to_str().unwrap_or("unknown error");
|
|
return Err(anyhow!("{maybe_str}"));
|
|
}
|
|
|
|
if self.content.is_null() {
|
|
return Err(anyhow!("response not provided"));
|
|
}
|
|
|
|
let content_cstr = unsafe { CStr::from_ptr(self.content) };
|
|
let node_response: NodeResponse = serde_json::from_slice(content_cstr.to_bytes())
|
|
.map_err(|_| anyhow!("failed to deserialize"))?;
|
|
|
|
Ok(node_response)
|
|
}
|
|
}
|