Files
zen/bindings/c/src/custom_node.rs
T
stefan-gorules daecf901e6 feat: custom node (#138)
* 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
2024-04-03 16:09:51 +02:00

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)
}
}