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

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, IStr, ManifestFormat, Val};13use std::{14	alloc::Layout,15	ffi::{CStr, CString},16	os::raw::{c_char, c_double, c_int, c_uint},17	path::PathBuf,18	rc::Rc,19};2021/// WASM stub22#[cfg(target_arch = "wasm32")]23#[no_mangle]24pub extern "C" fn _start() {}2526#[no_mangle]27pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {28	b"v0.16.0\0"29}3031#[no_mangle]32pub extern "C" fn jsonnet_make() -> *mut EvaluationState {33	let state = EvaluationState::default();34	state.with_stdlib();35	state.settings_mut().import_resolver = Box::new(NativeImportResolver::default());36	Box::into_raw(Box::new(state))37}3839/// # Safety40#[no_mangle]41#[allow(clippy::boxed_local)]42pub unsafe extern "C" fn jsonnet_destroy(vm: *mut EvaluationState) {43	Box::from_raw(vm);44}4546#[no_mangle]47pub extern "C" fn jsonnet_max_stack(vm: &EvaluationState, v: c_uint) {48	vm.settings_mut().max_stack = v as usize;49}5051// jrsonnet currently have no GC, so these functions is no-op52#[no_mangle]53pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}54#[no_mangle]55pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}5657#[no_mangle]58pub extern "C" fn jsonnet_string_output(vm: &EvaluationState, v: c_int) {59	match v {60		1 => vm.set_manifest_format(ManifestFormat::String),61		0 => vm.set_manifest_format(ManifestFormat::Json(4)),62		_ => panic!("incorrect output format"),63	}64}6566/// # Safety67///68/// This function is most definitely broken, but it works somehow, see TODO inside69#[no_mangle]70pub unsafe extern "C" fn jsonnet_realloc(71	_vm: &EvaluationState,72	buf: *mut u8,73	sz: usize,74) -> *mut u8 {75	if buf.is_null() {76		assert!(sz != 0);77		return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());78	}79	// TODO: Somehow store size of allocation, because its real size is probally not 16 :D80	// OR (Alternative way of fixing this TODO)81	// TODO: Standard allocator uses malloc, and it doesn't uses allocation size,82	// TODO: so it should work in normal cases. Maybe force allocator for this library?83	let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();84	if sz == 0 {85		std::alloc::dealloc(buf, old_layout);86		return std::ptr::null_mut();87	}88	std::alloc::realloc(buf, old_layout, sz)89}9091/// # Safety92#[no_mangle]93#[allow(clippy::boxed_local)]94pub unsafe extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, v: *mut Val) {95	Box::from_raw(v);96}9798#[no_mangle]99pub extern "C" fn jsonnet_max_trace(vm: &EvaluationState, v: c_uint) {100	vm.set_max_trace(v as usize)101}102103/// # Safety104///105/// This function is safe, if received v is a pointer to normal C string106#[no_mangle]107pub unsafe extern "C" fn jsonnet_evaluate_file(108	vm: &EvaluationState,109	filename: *const c_char,110	error: &mut c_int,111) -> *const c_char {112	vm.run_in_state(|| {113		let filename = CStr::from_ptr(filename);114		match vm115			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))116			.and_then(|v| vm.with_tla(v))117			.and_then(|v| vm.manifest(v))118		{119			Ok(v) => {120				*error = 0;121				CString::new(&*v as &str).unwrap().into_raw()122			}123			Err(e) => {124				*error = 1;125				let out = vm.stringify_err(&e);126				CString::new(&out as &str).unwrap().into_raw()127			}128		}129	})130}131132/// # Safety133///134/// This function is safe, if received v is a pointer to normal C string135#[no_mangle]136pub unsafe extern "C" fn jsonnet_evaluate_snippet(137	vm: &EvaluationState,138	filename: *const c_char,139	snippet: *const c_char,140	error: &mut c_int,141) -> *const c_char {142	vm.run_in_state(|| {143		let filename = CStr::from_ptr(filename);144		let snippet = CStr::from_ptr(snippet);145		match vm146			.evaluate_snippet_raw(147				Rc::new(PathBuf::from(filename.to_str().unwrap())),148				snippet.to_str().unwrap().into(),149			)150			.and_then(|v| vm.with_tla(v))151			.and_then(|v| vm.manifest(v))152		{153			Ok(v) => {154				*error = 0;155				CString::new(&*v as &str).unwrap().into_raw()156			}157			Err(e) => {158				*error = 1;159				let out = vm.stringify_err(&e);160				CString::new(&out as &str).unwrap().into_raw()161			}162		}163	})164}165166fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {167	let mut out = Vec::new();168	for (i, (k, v)) in multi.iter().enumerate() {169		if i != 0 {170			out.push(0);171		}172		out.extend_from_slice(k.as_bytes());173		out.push(0);174		out.extend_from_slice(v.as_bytes());175	}176	out.push(0);177	out.push(0);178	let v = out.as_ptr();179	std::mem::forget(out);180	v as *const c_char181}182183/// # Safety184#[no_mangle]185pub unsafe extern "C" fn jsonnet_evaluate_file_multi(186	vm: &EvaluationState,187	filename: *const c_char,188	error: &mut c_int,189) -> *const c_char {190	vm.run_in_state(|| {191		let filename = CStr::from_ptr(filename);192		match vm193			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))194			.and_then(|v| vm.with_tla(v))195			.and_then(|v| vm.manifest_multi(v))196		{197			Ok(v) => {198				*error = 0;199				multi_to_raw(v)200			}201			Err(e) => {202				*error = 1;203				let out = vm.stringify_err(&e);204				CString::new(&out as &str).unwrap().into_raw()205			}206		}207	})208}209210/// # Safety211#[no_mangle]212pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(213	vm: &EvaluationState,214	filename: *const c_char,215	snippet: *const c_char,216	error: &mut c_int,217) -> *const c_char {218	vm.run_in_state(|| {219		let filename = CStr::from_ptr(filename);220		let snippet = CStr::from_ptr(snippet);221		match vm222			.evaluate_snippet_raw(223				Rc::new(PathBuf::from(filename.to_str().unwrap())),224				snippet.to_str().unwrap().into(),225			)226			.and_then(|v| vm.with_tla(v))227			.and_then(|v| vm.manifest_multi(v))228		{229			Ok(v) => {230				*error = 0;231				multi_to_raw(v)232			}233			Err(e) => {234				*error = 1;235				let out = vm.stringify_err(&e);236				CString::new(&out as &str).unwrap().into_raw()237			}238		}239	})240}241242fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {243	let mut out = Vec::new();244	for (i, v) in multi.iter().enumerate() {245		if i != 0 {246			out.push(0);247		}248		out.extend_from_slice(v.as_bytes());249	}250	out.push(0);251	out.push(0);252	let v = out.as_ptr();253	std::mem::forget(out);254	v as *const c_char255}256257/// # Safety258#[no_mangle]259pub unsafe extern "C" fn jsonnet_evaluate_file_stream(260	vm: &EvaluationState,261	filename: *const c_char,262	error: &mut c_int,263) -> *const c_char {264	vm.run_in_state(|| {265		let filename = CStr::from_ptr(filename);266		match vm267			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))268			.and_then(|v| vm.with_tla(v))269			.and_then(|v| vm.manifest_stream(v))270		{271			Ok(v) => {272				*error = 0;273				stream_to_raw(v)274			}275			Err(e) => {276				*error = 1;277				let out = vm.stringify_err(&e);278				CString::new(&out as &str).unwrap().into_raw()279			}280		}281	})282}283284/// # Safety285#[no_mangle]286pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(287	vm: &EvaluationState,288	filename: *const c_char,289	snippet: *const c_char,290	error: &mut c_int,291) -> *const c_char {292	vm.run_in_state(|| {293		let filename = CStr::from_ptr(filename);294		let snippet = CStr::from_ptr(snippet);295		match vm296			.evaluate_snippet_raw(297				Rc::new(PathBuf::from(filename.to_str().unwrap())),298				snippet.to_str().unwrap().into(),299			)300			.and_then(|v| vm.with_tla(v))301			.and_then(|v| vm.manifest_stream(v))302		{303			Ok(v) => {304				*error = 0;305				stream_to_raw(v)306			}307			Err(e) => {308				*error = 1;309				let out = vm.stringify_err(&e);310				CString::new(&out as &str).unwrap().into_raw()311			}312		}313	})314}