1use std::{2 borrow::Cow,3 ffi::{c_void, CStr},4 os::raw::{c_char, c_int},5};67use jrsonnet_evaluator::{8 error::{Error, ErrorKind},9 function::builtin::{NativeCallback, NativeCallbackHandler},10 typed::Typed,11 IStr, Val,12};1314use crate::VM;1516171819202122232425type JsonnetNativeCallback = unsafe extern "C" fn(26 ctx: *const c_void,27 argv: *const *const Val,28 success: *mut c_int,29) -> *mut Val;3031#[derive(jrsonnet_gcmodule::Trace)]32struct JsonnetNativeCallbackHandler {33 #[trace(skip)]34 ctx: *const c_void,35 #[trace(skip)]36 cb: JsonnetNativeCallback,37}38impl NativeCallbackHandler for JsonnetNativeCallbackHandler {39 fn call(&self, args: &[Val]) -> Result<Val, Error> {40 let mut n_args = Vec::new();41 for a in args {42 n_args.push(Some(Box::new(a.clone())));43 }44 n_args.push(None);45 let mut success = 1;46 let v = unsafe { (self.cb)(self.ctx, n_args.as_ptr().cast(), &mut success) };47 let v = unsafe { *Box::from_raw(v) };48 if success == 1 {49 Ok(v)50 } else {51 let e = IStr::from_untyped(v).expect("error msg should be a string");52 Err(ErrorKind::RuntimeError(e).into())53 }54 }55}56575859606162636465#[no_mangle]66pub unsafe extern "C" fn jsonnet_native_callback(67 vm: &VM,68 name: *const c_char,69 cb: JsonnetNativeCallback,70 ctx: *const c_void,71 mut raw_params: *const *const c_char,72) {73 let name = CStr::from_ptr(name)74 .to_str()75 .expect("name is not utf-8")76 .into();77 let mut params = Vec::new();78 loop {79 if (*raw_params).is_null() {80 break;81 }82 let param = CStr::from_ptr(*raw_params)83 .to_str()84 .expect("param name is not utf-8");85 params.push(Cow::Owned(param.into()));86 raw_params = raw_params.offset(1);87 }8889 let any_resolver = vm.state.context_initializer();90 any_resolver91 .as_any()92 .downcast_ref::<jrsonnet_stdlib::ContextInitializer>()93 .expect("only stdlib context initializer supported")94 .add_native(95 name,96 #[allow(deprecated)]97 NativeCallback::new(params, JsonnetNativeCallbackHandler { ctx, cb }),98 )99}