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

difftreelog

source

bindings/jsonnet/src/lib.rs7.3 KiBsourcehistory
1#[cfg(feature = "interop")]2pub mod interop;34pub mod import;5pub mod native;6pub mod val_extract;7pub mod val_make;8pub mod val_modify;9pub mod vars_tlas;1011use import::NativeImportResolver;12use jrsonnet_evaluator::{EvaluationState, ManifestFormat, Val};13use jrsonnet_interner::IStr;14use std::{15	alloc::Layout,16	ffi::{CStr, CString},17	os::raw::{c_char, c_double, c_int, c_uint},18	path::PathBuf,19	rc::Rc,20};2122/// WASM stub23#[cfg(target_arch = "wasm32")]24#[no_mangle]25pub extern "C" fn _start() {}2627#[no_mangle]28pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {29	b"v0.16.0\0"30}3132#[no_mangle]33pub extern "C" fn jsonnet_make() -> *mut EvaluationState {34	let state = EvaluationState::default();35	state.with_stdlib();36	state.settings_mut().import_resolver = Box::new(NativeImportResolver::default());37	Box::into_raw(Box::new(state))38}3940/// # Safety41#[no_mangle]42#[allow(clippy::boxed_local)]43pub unsafe extern "C" fn jsonnet_destroy(vm: *mut EvaluationState) {44	Box::from_raw(vm);45}4647#[no_mangle]48pub extern "C" fn jsonnet_max_stack(vm: &EvaluationState, v: c_uint) {49	vm.settings_mut().max_stack = v as usize;50}5152// jrsonnet currently have no GC, so these functions is no-op53#[no_mangle]54pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}55#[no_mangle]56pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}5758#[no_mangle]59pub extern "C" fn jsonnet_string_output(vm: &EvaluationState, v: c_int) {60	match v {61		1 => vm.set_manifest_format(ManifestFormat::String),62		0 => vm.set_manifest_format(ManifestFormat::Json(4)),63		_ => panic!("incorrect output format"),64	}65}6667/// # Safety68///69/// This function is most definitely broken, but it works somehow, see TODO inside70#[no_mangle]71pub unsafe extern "C" fn jsonnet_realloc(72	_vm: &EvaluationState,73	buf: *mut u8,74	sz: usize,75) -> *mut u8 {76	if buf.is_null() {77		assert!(sz != 0);78		return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());79	}80	// TODO: Somehow store size of allocation, because its real size is probally not 16 :D81	// OR (Alternative way of fixing this TODO)82	// TODO: Standard allocator uses malloc, and it doesn't uses allocation size,83	// TODO: so it should work in normal cases. Maybe force allocator for this library?84	let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();85	if sz == 0 {86		std::alloc::dealloc(buf, old_layout);87		return std::ptr::null_mut();88	}89	std::alloc::realloc(buf, old_layout, sz)90}9192/// # Safety93#[no_mangle]94#[allow(clippy::boxed_local)]95pub unsafe extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, v: *mut Val) {96	Box::from_raw(v);97}9899#[no_mangle]100pub extern "C" fn jsonnet_max_trace(vm: &EvaluationState, v: c_uint) {101	vm.set_max_trace(v as usize)102}103104/// # Safety105///106/// This function is safe, if received v is a pointer to normal C string107#[no_mangle]108pub unsafe extern "C" fn jsonnet_evaluate_file(109	vm: &EvaluationState,110	filename: *const c_char,111	error: &mut c_int,112) -> *const c_char {113	vm.run_in_state(|| {114		let filename = CStr::from_ptr(filename);115		match vm116			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))117			.and_then(|v| vm.with_tla(v))118			.and_then(|v| vm.manifest(v))119		{120			Ok(v) => {121				*error = 0;122				CString::new(&*v as &str).unwrap().into_raw()123			}124			Err(e) => {125				*error = 1;126				let out = vm.stringify_err(&e);127				CString::new(&out as &str).unwrap().into_raw()128			}129		}130	})131}132133/// # Safety134///135/// This function is safe, if received v is a pointer to normal C string136#[no_mangle]137pub unsafe extern "C" fn jsonnet_evaluate_snippet(138	vm: &EvaluationState,139	filename: *const c_char,140	snippet: *const c_char,141	error: &mut c_int,142) -> *const c_char {143	vm.run_in_state(|| {144		let filename = CStr::from_ptr(filename);145		let snippet = CStr::from_ptr(snippet);146		match vm147			.evaluate_snippet_raw(148				Rc::new(PathBuf::from(filename.to_str().unwrap())),149				snippet.to_str().unwrap().into(),150			)151			.and_then(|v| vm.with_tla(v))152			.and_then(|v| vm.manifest(v))153		{154			Ok(v) => {155				*error = 0;156				CString::new(&*v as &str).unwrap().into_raw()157			}158			Err(e) => {159				*error = 1;160				let out = vm.stringify_err(&e);161				CString::new(&out as &str).unwrap().into_raw()162			}163		}164	})165}166167fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {168	let mut out = Vec::new();169	for (i, (k, v)) in multi.iter().enumerate() {170		if i != 0 {171			out.push(0);172		}173		out.extend_from_slice(k.as_bytes());174		out.push(0);175		out.extend_from_slice(v.as_bytes());176	}177	out.push(0);178	out.push(0);179	let v = out.as_ptr();180	std::mem::forget(out);181	v as *const c_char182}183184/// # Safety185#[no_mangle]186pub unsafe extern "C" fn jsonnet_evaluate_file_multi(187	vm: &EvaluationState,188	filename: *const c_char,189	error: &mut c_int,190) -> *const c_char {191	vm.run_in_state(|| {192		let filename = CStr::from_ptr(filename);193		match vm194			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))195			.and_then(|v| vm.with_tla(v))196			.and_then(|v| vm.manifest_multi(v))197		{198			Ok(v) => {199				*error = 0;200				multi_to_raw(v)201			}202			Err(e) => {203				*error = 1;204				let out = vm.stringify_err(&e);205				CString::new(&out as &str).unwrap().into_raw()206			}207		}208	})209}210211/// # Safety212#[no_mangle]213pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(214	vm: &EvaluationState,215	filename: *const c_char,216	snippet: *const c_char,217	error: &mut c_int,218) -> *const c_char {219	vm.run_in_state(|| {220		let filename = CStr::from_ptr(filename);221		let snippet = CStr::from_ptr(snippet);222		match vm223			.evaluate_snippet_raw(224				Rc::new(PathBuf::from(filename.to_str().unwrap())),225				snippet.to_str().unwrap().into(),226			)227			.and_then(|v| vm.with_tla(v))228			.and_then(|v| vm.manifest_multi(v))229		{230			Ok(v) => {231				*error = 0;232				multi_to_raw(v)233			}234			Err(e) => {235				*error = 1;236				let out = vm.stringify_err(&e);237				CString::new(&out as &str).unwrap().into_raw()238			}239		}240	})241}242243fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {244	let mut out = Vec::new();245	for (i, v) in multi.iter().enumerate() {246		if i != 0 {247			out.push(0);248		}249		out.extend_from_slice(v.as_bytes());250	}251	out.push(0);252	out.push(0);253	let v = out.as_ptr();254	std::mem::forget(out);255	v as *const c_char256}257258/// # Safety259#[no_mangle]260pub unsafe extern "C" fn jsonnet_evaluate_file_stream(261	vm: &EvaluationState,262	filename: *const c_char,263	error: &mut c_int,264) -> *const c_char {265	vm.run_in_state(|| {266		let filename = CStr::from_ptr(filename);267		match vm268			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))269			.and_then(|v| vm.with_tla(v))270			.and_then(|v| vm.manifest_stream(v))271		{272			Ok(v) => {273				*error = 0;274				stream_to_raw(v)275			}276			Err(e) => {277				*error = 1;278				let out = vm.stringify_err(&e);279				CString::new(&out as &str).unwrap().into_raw()280			}281		}282	})283}284285/// # Safety286#[no_mangle]287pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(288	vm: &EvaluationState,289	filename: *const c_char,290	snippet: *const c_char,291	error: &mut c_int,292) -> *const c_char {293	vm.run_in_state(|| {294		let filename = CStr::from_ptr(filename);295		let snippet = CStr::from_ptr(snippet);296		match vm297			.evaluate_snippet_raw(298				Rc::new(PathBuf::from(filename.to_str().unwrap())),299				snippet.to_str().unwrap().into(),300			)301			.and_then(|v| vm.with_tla(v))302			.and_then(|v| vm.manifest_stream(v))303		{304			Ok(v) => {305				*error = 0;306				stream_to_raw(v)307			}308			Err(e) => {309				*error = 1;310				let out = vm.stringify_err(&e);311				CString::new(&out as &str).unwrap().into_raw()312			}313		}314	})315}