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

difftreelog

source

bindings/jsonnet/src/lib.rs6.9 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 std::{12	alloc::Layout,13	ffi::{CStr, CString},14	os::raw::{c_char, c_double, c_int, c_uint},15	path::PathBuf,16};1718use import::NativeImportResolver;19use jrsonnet_evaluator::{IStr, ManifestFormat, State, Val};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 State {33	let state = State::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 State) {43	Box::from_raw(vm);44}4546#[no_mangle]47pub extern "C" fn jsonnet_max_stack(vm: &State, 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: &State, _v: c_uint) {}54#[no_mangle]55pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &State, _v: c_double) {}5657#[no_mangle]58pub extern "C" fn jsonnet_string_output(vm: &State, v: c_int) {59	match v {60		1 => vm.set_manifest_format(ManifestFormat::String),61		0 => vm.set_manifest_format(ManifestFormat::Json {62			padding: 4,63			#[cfg(feature = "exp-preserve-order")]64			preserve_order: false,65		}),66		_ => panic!("incorrect output format"),67	}68}6970/// # Safety71///72/// This function is most definitely broken, but it works somehow, see TODO inside73#[no_mangle]74pub unsafe extern "C" fn jsonnet_realloc(_vm: &State, buf: *mut u8, sz: usize) -> *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: &State, v: *mut Val) {95	Box::from_raw(v);96}9798#[no_mangle]99pub extern "C" fn jsonnet_max_trace(vm: &State, 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: &State,109	filename: *const c_char,110	error: &mut c_int,111) -> *const c_char {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}129130/// # Safety131///132/// This function is safe, if received v is a pointer to normal C string133#[no_mangle]134pub unsafe extern "C" fn jsonnet_evaluate_snippet(135	vm: &State,136	filename: *const c_char,137	snippet: *const c_char,138	error: &mut c_int,139) -> *const c_char {140	let filename = CStr::from_ptr(filename);141	let snippet = CStr::from_ptr(snippet);142	match vm143		.evaluate_snippet_raw(144			PathBuf::from(filename.to_str().unwrap()).into(),145			snippet.to_str().unwrap().into(),146		)147		.and_then(|v| vm.with_tla(v))148		.and_then(|v| vm.manifest(v))149	{150		Ok(v) => {151			*error = 0;152			CString::new(&*v as &str).unwrap().into_raw()153		}154		Err(e) => {155			*error = 1;156			let out = vm.stringify_err(&e);157			CString::new(&out as &str).unwrap().into_raw()158		}159	}160}161162fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {163	let mut out = Vec::new();164	for (i, (k, v)) in multi.iter().enumerate() {165		if i != 0 {166			out.push(0);167		}168		out.extend_from_slice(k.as_bytes());169		out.push(0);170		out.extend_from_slice(v.as_bytes());171	}172	out.push(0);173	out.push(0);174	let v = out.as_ptr();175	std::mem::forget(out);176	v as *const c_char177}178179/// # Safety180#[no_mangle]181pub unsafe extern "C" fn jsonnet_evaluate_file_multi(182	vm: &State,183	filename: *const c_char,184	error: &mut c_int,185) -> *const c_char {186	let filename = CStr::from_ptr(filename);187	match vm188		.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))189		.and_then(|v| vm.with_tla(v))190		.and_then(|v| vm.manifest_multi(v))191	{192		Ok(v) => {193			*error = 0;194			multi_to_raw(v)195		}196		Err(e) => {197			*error = 1;198			let out = vm.stringify_err(&e);199			CString::new(&out as &str).unwrap().into_raw()200		}201	}202}203204/// # Safety205#[no_mangle]206pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(207	vm: &State,208	filename: *const c_char,209	snippet: *const c_char,210	error: &mut c_int,211) -> *const c_char {212	let filename = CStr::from_ptr(filename);213	let snippet = CStr::from_ptr(snippet);214	match vm215		.evaluate_snippet_raw(216			PathBuf::from(filename.to_str().unwrap()).into(),217			snippet.to_str().unwrap().into(),218		)219		.and_then(|v| vm.with_tla(v))220		.and_then(|v| vm.manifest_multi(v))221	{222		Ok(v) => {223			*error = 0;224			multi_to_raw(v)225		}226		Err(e) => {227			*error = 1;228			let out = vm.stringify_err(&e);229			CString::new(&out as &str).unwrap().into_raw()230		}231	}232}233234fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {235	let mut out = Vec::new();236	for (i, v) in multi.iter().enumerate() {237		if i != 0 {238			out.push(0);239		}240		out.extend_from_slice(v.as_bytes());241	}242	out.push(0);243	out.push(0);244	let v = out.as_ptr();245	std::mem::forget(out);246	v as *const c_char247}248249/// # Safety250#[no_mangle]251pub unsafe extern "C" fn jsonnet_evaluate_file_stream(252	vm: &State,253	filename: *const c_char,254	error: &mut c_int,255) -> *const c_char {256	let filename = CStr::from_ptr(filename);257	match vm258		.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))259		.and_then(|v| vm.with_tla(v))260		.and_then(|v| vm.manifest_stream(v))261	{262		Ok(v) => {263			*error = 0;264			stream_to_raw(v)265		}266		Err(e) => {267			*error = 1;268			let out = vm.stringify_err(&e);269			CString::new(&out as &str).unwrap().into_raw()270		}271	}272}273274/// # Safety275#[no_mangle]276pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(277	vm: &State,278	filename: *const c_char,279	snippet: *const c_char,280	error: &mut c_int,281) -> *const c_char {282	let filename = CStr::from_ptr(filename);283	let snippet = CStr::from_ptr(snippet);284	match vm285		.evaluate_snippet_raw(286			PathBuf::from(filename.to_str().unwrap()).into(),287			snippet.to_str().unwrap().into(),288		)289		.and_then(|v| vm.with_tla(v))290		.and_then(|v| vm.manifest_stream(v))291	{292		Ok(v) => {293			*error = 0;294			stream_to_raw(v)295		}296		Err(e) => {297			*error = 1;298			let out = vm.stringify_err(&e);299			CString::new(&out as &str).unwrap().into_raw()300		}301	}302}