git.delta.rocks / jrsonnet / refs/commits / 1111100e839d

difftreelog

source

bindings/jsonnet/src/native.rs1.9 KiBsourcehistory
1use std::{2	convert::TryFrom,3	ffi::{c_void, CStr},4	os::raw::{c_char, c_int},5	path::Path,6	rc::Rc,7};89use gcmodule::Cc;10use jrsonnet_evaluator::{11	error::{Error, LocError},12	function::BuiltinParam,13	gc::TraceBox,14	native::{NativeCallback, NativeCallbackHandler},15	EvaluationState, IStr, Val,16};1718type JsonnetNativeCallback = unsafe extern "C" fn(19	ctx: *const c_void,20	argv: *const *const Val,21	success: *mut c_int,22) -> *mut Val;2324#[derive(gcmodule::Trace)]25struct JsonnetNativeCallbackHandler {26	#[skip_trace]27	ctx: *const c_void,28	#[skip_trace]29	cb: JsonnetNativeCallback,30}31impl NativeCallbackHandler for JsonnetNativeCallbackHandler {32	fn call(&self, _from: Option<Rc<Path>>, args: &[Val]) -> Result<Val, LocError> {33		let mut n_args = Vec::new();34		for a in args {35			n_args.push(Some(Box::new(a.clone())));36		}37		n_args.push(None);38		let mut success = 1;39		let v = unsafe {40			(self.cb)(41				self.ctx,42				&n_args as *const _ as *const *const Val,43				&mut success,44			)45		};46		let v = unsafe { *Box::from_raw(v) };47		if success == 1 {48			Ok(v)49		} else {50			let e = IStr::try_from(v).expect("error msg");51			Err(Error::RuntimeError(e).into())52		}53	}54}5556/// # Safety57#[no_mangle]58pub unsafe extern "C" fn jsonnet_native_callback(59	vm: &EvaluationState,60	name: *const c_char,61	cb: JsonnetNativeCallback,62	ctx: *const c_void,63	mut raw_params: *const *const c_char,64) {65	let name = CStr::from_ptr(name).to_str().expect("utf8 name").into();66	let mut params = Vec::new();67	loop {68		if (*raw_params).is_null() {69			break;70		}71		let param = CStr::from_ptr(*raw_params).to_str().expect("not utf8");72		params.push(BuiltinParam {73			name: param.into(),74			has_default: false,75		});76		raw_params = raw_params.offset(1);77	}7879	vm.add_native(80		name,81		#[allow(deprecated)]82		Cc::new(TraceBox(Box::new(NativeCallback::new(83			params,84			TraceBox(Box::new(JsonnetNativeCallbackHandler { ctx, cb })),85		)))),86	)87}