1use std::{2 ffi::{c_void, CStr},3 os::raw::{c_char, c_int},4};56use jrsonnet_evaluator::{7 error::{Error, LocError},8 function::builtin::{BuiltinParam, NativeCallback, NativeCallbackHandler},9 tb,10 typed::Typed,11 IStr, State, Val,12};13use jrsonnet_gcmodule::Cc;1415161718192021222324type JsonnetNativeCallback = unsafe extern "C" fn(25 ctx: *const c_void,26 argv: *const *const Val,27 success: *mut c_int,28) -> *mut Val;2930#[derive(jrsonnet_gcmodule::Trace)]31struct JsonnetNativeCallbackHandler {32 #[trace(skip)]33 ctx: *const c_void,34 #[trace(skip)]35 cb: JsonnetNativeCallback,36}37impl NativeCallbackHandler for JsonnetNativeCallbackHandler {38 fn call(&self, s: State, args: &[Val]) -> Result<Val, LocError> {39 let mut n_args = Vec::new();40 for a in args {41 n_args.push(Some(Box::new(a.clone())));42 }43 n_args.push(None);44 let mut success = 1;45 let v = unsafe {46 (self.cb)(47 self.ctx,48 &n_args as *const _ as *const *const Val,49 &mut success,50 )51 };52 let v = unsafe { *Box::from_raw(v) };53 if success == 1 {54 Ok(v)55 } else {56 let e = IStr::from_untyped(v, s).expect("error msg should be a string");57 Err(Error::RuntimeError(e).into())58 }59 }60}61626364656667686970#[no_mangle]71pub unsafe extern "C" fn jsonnet_native_callback(72 vm: &State,73 name: *const c_char,74 cb: JsonnetNativeCallback,75 ctx: *const c_void,76 mut raw_params: *const *const c_char,77) {78 let name = CStr::from_ptr(name)79 .to_str()80 .expect("name is not utf-8")81 .into();82 let mut params = Vec::new();83 loop {84 if (*raw_params).is_null() {85 break;86 }87 let param = CStr::from_ptr(*raw_params)88 .to_str()89 .expect("param name is not utf-8");90 params.push(BuiltinParam {91 name: param.into(),92 has_default: false,93 });94 raw_params = raw_params.offset(1);95 }9697 let any_resolver = vm.context_initializer();98 any_resolver99 .as_any()100 .downcast_ref::<jrsonnet_stdlib::ContextInitializer>()101 .expect("only stdlib context initializer supported")102 .add_native(103 name,104 #[allow(deprecated)]105 Cc::new(tb!(NativeCallback::new(106 params,107 tb!(JsonnetNativeCallbackHandler { ctx, cb }),108 ))),109 )110}