git.delta.rocks / jrsonnet / refs/commits / 5858c9313e03

difftreelog

source

bindings/jsonnet/src/interop.rs3.9 KiBsourcehistory
1//! Jrsonnet specific additional binding helpers23#[cfg(feature = "interop-wasm")]4pub mod wasm {5	use std::ffi::{c_char, c_int, c_void};67	use jrsonnet_evaluator::Val;89	use crate::VM;1011	extern "C" {1213		pub fn _jrsonnet_static_import_callback(14			ctx: *mut c_void,15			base: *const c_char,16			rel: *const c_char,17			found_here: *mut *const c_char,18			buf: *mut *mut c_char,19			buflen: *mut usize,20		) -> c_int;2122		#[allow(improper_ctypes)]23		pub fn _jrsonnet_static_native_callback(24			ctx: *const c_void,25			argv: *const *const Val,26			success: *mut c_int,27		) -> *mut Val;28	}2930	#[no_mangle]31	#[cfg(feature = "interop-wasm")]32	// ctx arg is passed as-is to callback33	#[allow(clippy::not_unsafe_ptr_arg_deref)]34	pub extern "C" fn jrsonnet_apply_static_import_callback(vm: &VM, ctx: *mut c_void) {35		unsafe { crate::import::jsonnet_import_callback(vm, _jrsonnet_static_import_callback, ctx) }36	}3738	/// # Safety39	///40	/// `name` and `raw_params` should be correctly initialized41	#[no_mangle]42	#[cfg(feature = "interop-wasm")]43	pub unsafe extern "C" fn jrsonnet_apply_static_native_callback(44		vm: &VM,45		name: *const c_char,46		ctx: *mut c_void,47		raw_params: *const *const c_char,48	) {49		unsafe {50			crate::native::jsonnet_native_callback(51				vm,52				name,53				_jrsonnet_static_native_callback,54				ctx,55				raw_params,56			);57		}58	}59}6061#[cfg(feature = "interop-common")]62mod common {63	use jrsonnet_evaluator::trace::{CompactFormat, HiDocFormat, JsFormat, PathResolver};6465	use crate::VM;6667	#[no_mangle]68	pub extern "C" fn jrsonnet_set_trace_format(vm: &mut VM, format: u8) {69		match format {70			0 => {71				vm.trace_format = Box::new(CompactFormat {72					max_trace: 20,73					resolver: PathResolver::new_cwd_fallback(),74					padding: 4,75				});76			}77			1 => vm.trace_format = Box::new(JsFormat { max_trace: 20 }),78			2 => {79				vm.trace_format = Box::new(HiDocFormat {80					resolver: PathResolver::new_cwd_fallback(),81					max_trace: 20,82				});83			}84			_ => panic!("unknown trace format"),85		}86	}87}8889#[cfg(feature = "interop-threading")]90mod threading {91	use std::{ffi::c_int, thread::ThreadId};9293	pub struct ThreadCTX {94		interner: *mut jrsonnet_interner::interop::PoolState,95		gc: *mut jrsonnet_gcmodule::interop::GcState,96	}9798	/// Golang jrsonnet bindings require Jsonnet VM to be movable.99	/// Jrsonnet uses `thread_local` in some places, thus making VM100	/// immovable by default. By using `jrsonnet_exit_thread` and101	/// `jrsonnet_reenter_thread`, you can move `thread_local` state to102	/// where it is more convinient to use it.103	///104	/// # Safety105	///106	/// Current thread GC will be broken after this call, need to call107	/// `jrsonet_enter_thread` before doing anything.108	#[no_mangle]109	pub unsafe extern "C" fn jrsonnet_exit_thread() -> *mut ThreadCTX {110		Box::into_raw(Box::new(ThreadCTX {111			interner: jrsonnet_interner::interop::exit_thread(),112			gc: unsafe { jrsonnet_gcmodule::interop::exit_thread() },113		}))114	}115116	#[no_mangle]117	pub extern "C" fn jrsonnet_reenter_thread(mut ctx: Box<ThreadCTX>) {118		use std::ptr::null_mut;119		assert!(120			!ctx.interner.is_null() && !ctx.gc.is_null(),121			"reused context?"122		);123		unsafe { jrsonnet_interner::interop::reenter_thread(ctx.interner) }124		unsafe { jrsonnet_gcmodule::interop::reenter_thread(ctx.gc) }125		// Just in case126		ctx.interner = null_mut();127		ctx.gc = null_mut();128	}129130	// ThreadId is compatible with u64, and there is unstable cast131	// method... But until it is stabilized, lets erase its type by132	// boxing.133	pub enum JrThreadId {}134135	#[no_mangle]136	pub extern "C" fn jrsonnet_thread_id() -> *mut JrThreadId {137		Box::into_raw(Box::new(std::thread::current().id())).cast()138	}139140	#[no_mangle]141	pub extern "C" fn jrsonnet_thread_id_compare(142		a: *const JrThreadId,143		b: *const JrThreadId,144	) -> c_int {145		let a: &ThreadId = unsafe { *a.cast() };146		let b: &ThreadId = unsafe { *b.cast() };147		i32::from(*a == *b)148	}149150	#[no_mangle]151	pub unsafe extern "C" fn jrsonnet_thread_id_free(id: *mut JrThreadId) {152		let _id: Box<ThreadId> = unsafe { Box::from_raw(id.cast()) };153	}154}