2025-08-08 06:56:49 +02:00
|
|
|
use std::collections::HashMap;
|
2025-08-07 21:10:17 +02:00
|
|
|
use std::mem;
|
|
|
|
|
use std::slice;
|
|
|
|
|
use std::str;
|
|
|
|
|
|
2025-08-08 06:56:49 +02:00
|
|
|
use cel::{Context, Program, Value};
|
|
|
|
|
use serde_json;
|
2025-08-07 21:10:17 +02:00
|
|
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
|
|
|
|
pub extern "C" fn allocation(n: usize) -> *mut u8 {
|
|
|
|
|
mem::ManuallyDrop::new(Vec::with_capacity(n)).as_mut_ptr()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[unsafe(no_mangle)]
|
|
|
|
|
pub unsafe extern "C" fn evaluate(s: *const u8) -> *mut u8 {
|
|
|
|
|
unsafe {
|
|
|
|
|
let length = u32::from_le_bytes(*(s as *const [u8; 4])) as usize;
|
|
|
|
|
let input = slice::from_raw_parts(s.offset(4), length);
|
|
|
|
|
let output = evaluate_buffers(input);
|
|
|
|
|
mem::ManuallyDrop::new(output).as_mut_ptr()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn evaluate_buffers(input: &[u8]) -> Vec<u8> {
|
|
|
|
|
let contents = str::from_utf8(input).unwrap();
|
2025-08-08 06:56:49 +02:00
|
|
|
let result = evaluate_cel_with_context(contents);
|
2025-08-07 21:10:17 +02:00
|
|
|
let success = result.is_ok();
|
2025-08-08 06:56:49 +02:00
|
|
|
let message = result.unwrap_or_else(|e| e);
|
2025-08-07 21:10:17 +02:00
|
|
|
let len = message.len();
|
|
|
|
|
let mut buffer = Vec::with_capacity(len + 8);
|
|
|
|
|
buffer.push(if success { 1 } else { 0 });
|
|
|
|
|
buffer.extend(vec![0; 3]);
|
|
|
|
|
buffer.extend_from_slice(&(len as u32).to_le_bytes());
|
|
|
|
|
buffer.extend_from_slice(message.as_bytes());
|
|
|
|
|
buffer
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-08 06:56:49 +02:00
|
|
|
fn json_to_cel_value(json_value: &serde_json::Value) -> Value {
|
|
|
|
|
match json_value {
|
|
|
|
|
serde_json::Value::Null => Value::Null,
|
|
|
|
|
serde_json::Value::Bool(b) => Value::Bool(*b),
|
|
|
|
|
serde_json::Value::Number(n) => {
|
|
|
|
|
if let Some(i) = n.as_i64() {
|
|
|
|
|
Value::Int(i)
|
|
|
|
|
} else if let Some(f) = n.as_f64() {
|
|
|
|
|
Value::Float(f)
|
|
|
|
|
} else {
|
|
|
|
|
Value::Null
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
serde_json::Value::String(s) => Value::String(s.clone().into()),
|
|
|
|
|
serde_json::Value::Array(arr) => {
|
|
|
|
|
let cel_vec: Vec<Value> = arr.iter().map(json_to_cel_value).collect();
|
|
|
|
|
Value::List(cel_vec.into())
|
|
|
|
|
}
|
|
|
|
|
serde_json::Value::Object(obj) => {
|
|
|
|
|
let mut cel_map = HashMap::new();
|
|
|
|
|
for (key, value) in obj.iter() {
|
|
|
|
|
cel_map.insert(key.clone(), json_to_cel_value(value));
|
|
|
|
|
}
|
|
|
|
|
Value::Map(cel_map.into())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn evaluate_cel_with_context(content: &str) -> Result<String, String> {
|
|
|
|
|
// Split the input to get expression and context
|
|
|
|
|
let parts: Vec<&str> = content.split("\n---CONTEXT---\n").collect();
|
|
|
|
|
let expression = parts[0].trim();
|
|
|
|
|
let context_json = if parts.len() > 1 {
|
|
|
|
|
parts[1].trim()
|
|
|
|
|
} else {
|
|
|
|
|
"{}"
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Parse the CEL expression
|
|
|
|
|
let program = match Program::compile(expression) {
|
|
|
|
|
Ok(prog) => prog,
|
|
|
|
|
Err(e) => return Err(format!("Compilation error: {}", e)),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Create context and add JSON values
|
2025-08-07 21:10:17 +02:00
|
|
|
let mut context = Context::default();
|
2025-08-08 06:56:49 +02:00
|
|
|
|
|
|
|
|
// Parse JSON context if provided and not empty
|
|
|
|
|
if !context_json.is_empty() && context_json != "{}" {
|
|
|
|
|
match serde_json::from_str::<serde_json::Value>(context_json) {
|
|
|
|
|
Ok(json_value) => {
|
|
|
|
|
if let serde_json::Value::Object(obj) = json_value {
|
|
|
|
|
for (key, value) in obj.iter() {
|
|
|
|
|
let cel_value = json_to_cel_value(value);
|
|
|
|
|
context
|
|
|
|
|
.add_variable(key, cel_value)
|
|
|
|
|
.map_err(|e| format!("Context error: {}", e))?;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return Err("JSON context must be an object".to_string());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Err(e) => return Err(format!("JSON parsing error: {}", e)),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Execute the program
|
|
|
|
|
match program.execute(&context) {
|
|
|
|
|
Ok(value) => Ok(format!("{:?}", value)),
|
|
|
|
|
Err(e) => Err(format!("Execution error: {}", e)),
|
|
|
|
|
}
|
2025-08-07 21:10:17 +02:00
|
|
|
}
|