git.delta.rocks / jrsonnet / refs/commits / 69d179bf913a

difftreelog

source

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