git.delta.rocks / jrsonnet / refs/commits / 68c8ac05879f

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.settings_mut().import_resolver = Box::new(NativeImportResolver::default());35	state.settings_mut().context_initializer =36		Box::new(jrsonnet_stdlib::ContextInitializer::new(state.clone()));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 State) {44	drop(Box::from_raw(vm));45}4647#[no_mangle]48pub extern "C" fn jsonnet_max_stack(vm: &State, 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: &State, _v: c_uint) {}55#[no_mangle]56pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &State, _v: c_double) {}5758#[no_mangle]59pub extern "C" fn jsonnet_string_output(vm: &State, v: c_int) {60	match v {61		1 => vm.set_manifest_format(ManifestFormat::String),62		0 => vm.set_manifest_format(ManifestFormat::Json {63			padding: 4,64			#[cfg(feature = "exp-preserve-order")]65			preserve_order: false,66		}),67		_ => panic!("incorrect output format"),68	}69}7071/// # Safety72///73/// This function is most definitely broken, but it works somehow, see TODO inside74#[no_mangle]75pub unsafe extern "C" fn jsonnet_realloc(_vm: &State, buf: *mut u8, sz: usize) -> *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: &State, v: *mut Val) {96	drop(Box::from_raw(v));97}9899#[no_mangle]100pub extern "C" fn jsonnet_max_trace(vm: &State, 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: &State,110	filename: *const c_char,111	error: &mut c_int,112) -> *const c_char {113	let filename = CStr::from_ptr(filename);114	match vm115		.import(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}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: &State,137	filename: *const c_char,138	snippet: *const c_char,139	error: &mut c_int,140) -> *const c_char {141	let filename = CStr::from_ptr(filename);142	let snippet = CStr::from_ptr(snippet);143	match vm144		.evaluate_snippet(145			filename.to_str().unwrap().into(),146			snippet.to_str().unwrap().into(),147		)148		.and_then(|v| vm.with_tla(v))149		.and_then(|v| vm.manifest(v))150	{151		Ok(v) => {152			*error = 0;153			CString::new(&*v as &str).unwrap().into_raw()154		}155		Err(e) => {156			*error = 1;157			let out = vm.stringify_err(&e);158			CString::new(&out as &str).unwrap().into_raw()159		}160	}161}162163fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {164	let mut out = Vec::new();165	for (i, (k, v)) in multi.iter().enumerate() {166		if i != 0 {167			out.push(0);168		}169		out.extend_from_slice(k.as_bytes());170		out.push(0);171		out.extend_from_slice(v.as_bytes());172	}173	out.push(0);174	out.push(0);175	let v = out.as_ptr();176	std::mem::forget(out);177	v as *const c_char178}179180/// # Safety181#[no_mangle]182pub unsafe extern "C" fn jsonnet_evaluate_file_multi(183	vm: &State,184	filename: *const c_char,185	error: &mut c_int,186) -> *const c_char {187	let filename = CStr::from_ptr(filename);188	match vm189		.import(PathBuf::from(filename.to_str().unwrap()))190		.and_then(|v| vm.with_tla(v))191		.and_then(|v| vm.manifest_multi(v))192	{193		Ok(v) => {194			*error = 0;195			multi_to_raw(v)196		}197		Err(e) => {198			*error = 1;199			let out = vm.stringify_err(&e);200			CString::new(&out as &str).unwrap().into_raw()201		}202	}203}204205/// # Safety206#[no_mangle]207pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(208	vm: &State,209	filename: *const c_char,210	snippet: *const c_char,211	error: &mut c_int,212) -> *const c_char {213	let filename = CStr::from_ptr(filename);214	let snippet = CStr::from_ptr(snippet);215	match vm216		.evaluate_snippet(217			filename.to_str().unwrap().into(),218			snippet.to_str().unwrap().into(),219		)220		.and_then(|v| vm.with_tla(v))221		.and_then(|v| vm.manifest_multi(v))222	{223		Ok(v) => {224			*error = 0;225			multi_to_raw(v)226		}227		Err(e) => {228			*error = 1;229			let out = vm.stringify_err(&e);230			CString::new(&out as &str).unwrap().into_raw()231		}232	}233}234235fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {236	let mut out = Vec::new();237	for (i, v) in multi.iter().enumerate() {238		if i != 0 {239			out.push(0);240		}241		out.extend_from_slice(v.as_bytes());242	}243	out.push(0);244	out.push(0);245	let v = out.as_ptr();246	std::mem::forget(out);247	v as *const c_char248}249250/// # Safety251#[no_mangle]252pub unsafe extern "C" fn jsonnet_evaluate_file_stream(253	vm: &State,254	filename: *const c_char,255	error: &mut c_int,256) -> *const c_char {257	let filename = CStr::from_ptr(filename);258	match vm259		.import(PathBuf::from(filename.to_str().unwrap()))260		.and_then(|v| vm.with_tla(v))261		.and_then(|v| vm.manifest_stream(v))262	{263		Ok(v) => {264			*error = 0;265			stream_to_raw(v)266		}267		Err(e) => {268			*error = 1;269			let out = vm.stringify_err(&e);270			CString::new(&out as &str).unwrap().into_raw()271		}272	}273}274275/// # Safety276#[no_mangle]277pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(278	vm: &State,279	filename: *const c_char,280	snippet: *const c_char,281	error: &mut c_int,282) -> *const c_char {283	let filename = CStr::from_ptr(filename);284	let snippet = CStr::from_ptr(snippet);285	match vm286		.evaluate_snippet(287			filename.to_str().unwrap().into(),288			snippet.to_str().unwrap().into(),289		)290		.and_then(|v| vm.with_tla(v))291		.and_then(|v| vm.manifest_stream(v))292	{293		Ok(v) => {294			*error = 0;295			stream_to_raw(v)296		}297		Err(e) => {298			*error = 1;299			let out = vm.stringify_err(&e);300			CString::new(&out as &str).unwrap().into_raw()301		}302	}303}