git.delta.rocks / jrsonnet / refs/commits / 74199ce77317

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};1920/// WASM stub21#[cfg(target_arch = "wasm32")]22#[no_mangle]23pub extern "C" fn _start() {}2425#[no_mangle]26pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {27	b"v0.16.0\0"28}2930#[no_mangle]31pub extern "C" fn jsonnet_make() -> *mut EvaluationState {32	let state = EvaluationState::default();33	state.with_stdlib();34	state.settings_mut().import_resolver = Box::new(NativeImportResolver::default());35	Box::into_raw(Box::new(state))36}3738/// # Safety39#[no_mangle]40#[allow(clippy::boxed_local)]41pub unsafe extern "C" fn jsonnet_destroy(vm: *mut EvaluationState) {42	Box::from_raw(vm);43}4445#[no_mangle]46pub extern "C" fn jsonnet_max_stack(vm: &EvaluationState, v: c_uint) {47	vm.settings_mut().max_stack = v as usize;48}4950// jrsonnet currently have no GC, so these functions is no-op51#[no_mangle]52pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}53#[no_mangle]54pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}5556#[no_mangle]57pub extern "C" fn jsonnet_string_output(vm: &EvaluationState, v: c_int) {58	match v {59		1 => vm.set_manifest_format(ManifestFormat::String),60		0 => vm.set_manifest_format(ManifestFormat::Json(4)),61		_ => panic!("incorrect output format"),62	}63}6465/// # Safety66///67/// This function is most definitely broken, but it works somehow, see TODO inside68#[no_mangle]69pub unsafe extern "C" fn jsonnet_realloc(70	_vm: &EvaluationState,71	buf: *mut u8,72	sz: usize,73) -> *mut u8 {74	if buf.is_null() {75		assert!(sz != 0);76		return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());77	}78	// TODO: Somehow store size of allocation, because its real size is probally not 16 :D79	// OR (Alternative way of fixing this TODO)80	// TODO: Standard allocator uses malloc, and it doesn't uses allocation size,81	// TODO: so it should work in normal cases. Maybe force allocator for this library?82	let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();83	if sz == 0 {84		std::alloc::dealloc(buf, old_layout);85		return std::ptr::null_mut();86	}87	std::alloc::realloc(buf, old_layout, sz)88}8990/// # Safety91#[no_mangle]92#[allow(clippy::boxed_local)]93pub unsafe extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, v: *mut Val) {94	Box::from_raw(v);95}9697#[no_mangle]98pub extern "C" fn jsonnet_max_trace(vm: &EvaluationState, v: c_uint) {99	vm.set_max_trace(v as usize)100}101102/// # Safety103///104/// This function is safe, if received v is a pointer to normal C string105#[no_mangle]106pub unsafe extern "C" fn jsonnet_evaluate_file(107	vm: &EvaluationState,108	filename: *const c_char,109	error: &mut c_int,110) -> *const c_char {111	vm.run_in_state(|| {112		let filename = CStr::from_ptr(filename);113		match vm114			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))115			.and_then(|v| vm.with_tla(v))116			.and_then(|v| vm.manifest(v))117		{118			Ok(v) => {119				*error = 0;120				CString::new(&*v as &str).unwrap().into_raw()121			}122			Err(e) => {123				*error = 1;124				let out = vm.stringify_err(&e);125				CString::new(&out as &str).unwrap().into_raw()126			}127		}128	})129}130131/// # Safety132///133/// This function is safe, if received v is a pointer to normal C string134#[no_mangle]135pub unsafe extern "C" fn jsonnet_evaluate_snippet(136	vm: &EvaluationState,137	filename: *const c_char,138	snippet: *const c_char,139	error: &mut c_int,140) -> *const c_char {141	vm.run_in_state(|| {142		let filename = CStr::from_ptr(filename);143		let snippet = CStr::from_ptr(snippet);144		match vm145			.evaluate_snippet_raw(146				PathBuf::from(filename.to_str().unwrap()).into(),147				snippet.to_str().unwrap().into(),148			)149			.and_then(|v| vm.with_tla(v))150			.and_then(|v| vm.manifest(v))151		{152			Ok(v) => {153				*error = 0;154				CString::new(&*v as &str).unwrap().into_raw()155			}156			Err(e) => {157				*error = 1;158				let out = vm.stringify_err(&e);159				CString::new(&out as &str).unwrap().into_raw()160			}161		}162	})163}164165fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {166	let mut out = Vec::new();167	for (i, (k, v)) in multi.iter().enumerate() {168		if i != 0 {169			out.push(0);170		}171		out.extend_from_slice(k.as_bytes());172		out.push(0);173		out.extend_from_slice(v.as_bytes());174	}175	out.push(0);176	out.push(0);177	let v = out.as_ptr();178	std::mem::forget(out);179	v as *const c_char180}181182/// # Safety183#[no_mangle]184pub unsafe extern "C" fn jsonnet_evaluate_file_multi(185	vm: &EvaluationState,186	filename: *const c_char,187	error: &mut c_int,188) -> *const c_char {189	vm.run_in_state(|| {190		let filename = CStr::from_ptr(filename);191		match vm192			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))193			.and_then(|v| vm.with_tla(v))194			.and_then(|v| vm.manifest_multi(v))195		{196			Ok(v) => {197				*error = 0;198				multi_to_raw(v)199			}200			Err(e) => {201				*error = 1;202				let out = vm.stringify_err(&e);203				CString::new(&out as &str).unwrap().into_raw()204			}205		}206	})207}208209/// # Safety210#[no_mangle]211pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(212	vm: &EvaluationState,213	filename: *const c_char,214	snippet: *const c_char,215	error: &mut c_int,216) -> *const c_char {217	vm.run_in_state(|| {218		let filename = CStr::from_ptr(filename);219		let snippet = CStr::from_ptr(snippet);220		match vm221			.evaluate_snippet_raw(222				PathBuf::from(filename.to_str().unwrap()).into(),223				snippet.to_str().unwrap().into(),224			)225			.and_then(|v| vm.with_tla(v))226			.and_then(|v| vm.manifest_multi(v))227		{228			Ok(v) => {229				*error = 0;230				multi_to_raw(v)231			}232			Err(e) => {233				*error = 1;234				let out = vm.stringify_err(&e);235				CString::new(&out as &str).unwrap().into_raw()236			}237		}238	})239}240241fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {242	let mut out = Vec::new();243	for (i, v) in multi.iter().enumerate() {244		if i != 0 {245			out.push(0);246		}247		out.extend_from_slice(v.as_bytes());248	}249	out.push(0);250	out.push(0);251	let v = out.as_ptr();252	std::mem::forget(out);253	v as *const c_char254}255256/// # Safety257#[no_mangle]258pub unsafe extern "C" fn jsonnet_evaluate_file_stream(259	vm: &EvaluationState,260	filename: *const c_char,261	error: &mut c_int,262) -> *const c_char {263	vm.run_in_state(|| {264		let filename = CStr::from_ptr(filename);265		match vm266			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))267			.and_then(|v| vm.with_tla(v))268			.and_then(|v| vm.manifest_stream(v))269		{270			Ok(v) => {271				*error = 0;272				stream_to_raw(v)273			}274			Err(e) => {275				*error = 1;276				let out = vm.stringify_err(&e);277				CString::new(&out as &str).unwrap().into_raw()278			}279		}280	})281}282283/// # Safety284#[no_mangle]285pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(286	vm: &EvaluationState,287	filename: *const c_char,288	snippet: *const c_char,289	error: &mut c_int,290) -> *const c_char {291	vm.run_in_state(|| {292		let filename = CStr::from_ptr(filename);293		let snippet = CStr::from_ptr(snippet);294		match vm295			.evaluate_snippet_raw(296				PathBuf::from(filename.to_str().unwrap()).into(),297				snippet.to_str().unwrap().into(),298			)299			.and_then(|v| vm.with_tla(v))300			.and_then(|v| vm.manifest_stream(v))301		{302			Ok(v) => {303				*error = 0;304				stream_to_raw(v)305			}306			Err(e) => {307				*error = 1;308				let out = vm.stringify_err(&e);309				CString::new(&out as &str).unwrap().into_raw()310			}311		}312	})313}