mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 08:02:28 +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
75 lines
2.2 KiB
Rust
75 lines
2.2 KiB
Rust
use crate::languages::native::NativeDecisionLoader;
|
|
use anyhow::anyhow;
|
|
use async_trait::async_trait;
|
|
use std::ffi::{c_char, CStr, CString};
|
|
use std::sync::Arc;
|
|
use zen_engine::loader::{DecisionLoader, LoaderError, LoaderResponse, NoopLoader};
|
|
use zen_engine::model::DecisionContent;
|
|
|
|
#[derive(Debug)]
|
|
pub(crate) enum DynamicDecisionLoader {
|
|
Noop(NoopLoader),
|
|
Native(NativeDecisionLoader),
|
|
#[cfg(feature = "go")]
|
|
Go(crate::languages::go::GoDecisionLoader),
|
|
}
|
|
|
|
impl Default for DynamicDecisionLoader {
|
|
fn default() -> Self {
|
|
Self::Noop(Default::default())
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl DecisionLoader for DynamicDecisionLoader {
|
|
async fn load(&self, key: &str) -> LoaderResponse {
|
|
match self {
|
|
DynamicDecisionLoader::Noop(loader) => loader.load(key).await,
|
|
DynamicDecisionLoader::Native(loader) => loader.load(key).await,
|
|
#[cfg(feature = "go")]
|
|
DynamicDecisionLoader::Go(loader) => loader.load(key).await,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[repr(C)]
|
|
pub struct ZenDecisionLoaderResult {
|
|
content: *mut c_char,
|
|
error: *mut c_char,
|
|
}
|
|
|
|
impl ZenDecisionLoaderResult {
|
|
pub fn into_loader_response(self, key: &str) -> LoaderResponse {
|
|
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 {
|
|
return Err(LoaderError::Internal {
|
|
key: key.to_string(),
|
|
source: anyhow!(c_error.to_string_lossy().to_string()),
|
|
}
|
|
.into());
|
|
}
|
|
|
|
let maybe_content = match self.content.is_null() {
|
|
false => Some(unsafe { CStr::from_ptr(self.content) }),
|
|
true => None,
|
|
};
|
|
|
|
// If both pointers are null, we are treating it as not found
|
|
let Some(c_content) = maybe_content else {
|
|
return Err(LoaderError::NotFound(key.to_string()).into());
|
|
};
|
|
|
|
let decision_content: DecisionContent = serde_json::from_slice(c_content.to_bytes())
|
|
.map_err(|e| LoaderError::Internal {
|
|
key: key.to_string(),
|
|
source: anyhow!(e),
|
|
})?;
|
|
|
|
Ok(Arc::new(decision_content))
|
|
}
|
|
}
|