git.delta.rocks / jrsonnet / refs/commits / d76beb28c515

difftreelog

source

bindings/jsonnet/src/native.rs1.8 KiBsourcehistory
1use std::{2	ffi::{c_void, CStr},3	os::raw::{c_char, c_int},4};56use gcmodule::Cc;7use jrsonnet_evaluator::{8	error::{Error, LocError},9	function::builtin::{BuiltinParam, NativeCallback, NativeCallbackHandler},10	tb,11	typed::Typed,12	IStr, State, Val,13};1415type JsonnetNativeCallback = unsafe extern "C" fn(16	ctx: *const c_void,17	argv: *const *const Val,18	success: *mut c_int,19) -> *mut Val;2021#[derive(gcmodule::Trace)]22struct JsonnetNativeCallbackHandler {23	#[skip_trace]24	ctx: *const c_void,25	#[skip_trace]26	cb: JsonnetNativeCallback,27}28impl NativeCallbackHandler for JsonnetNativeCallbackHandler {29	fn call(&self, s: State, args: &[Val]) -> Result<Val, LocError> {30		let mut n_args = Vec::new();31		for a in args {32			n_args.push(Some(Box::new(a.clone())));33		}34		n_args.push(None);35		let mut success = 1;36		let v = unsafe {37			(self.cb)(38				self.ctx,39				&n_args as *const _ as *const *const Val,40				&mut success,41			)42		};43		let v = unsafe { *Box::from_raw(v) };44		if success == 1 {45			Ok(v)46		} else {47			let e = IStr::from_untyped(v, s).expect("error msg");48			Err(Error::RuntimeError(e).into())49		}50	}51}5253/// # Safety54#[no_mangle]55pub unsafe extern "C" fn jsonnet_native_callback(56	vm: &State,57	name: *const c_char,58	cb: JsonnetNativeCallback,59	ctx: *const c_void,60	mut raw_params: *const *const c_char,61) {62	let name = CStr::from_ptr(name).to_str().expect("utf8 name").into();63	let mut params = Vec::new();64	loop {65		if (*raw_params).is_null() {66			break;67		}68		let param = CStr::from_ptr(*raw_params).to_str().expect("not utf8");69		params.push(BuiltinParam {70			name: param.into(),71			has_default: false,72		});73		raw_params = raw_params.offset(1);74	}7576	vm.add_native(77		name,78		#[allow(deprecated)]79		Cc::new(tb!(NativeCallback::new(80			params,81			tb!(JsonnetNativeCallbackHandler { ctx, cb }),82		))),83	)84}