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 borrow::Cow,14 ffi::{CStr, CString, OsStr},15 os::raw::{c_char, c_double, c_int, c_uint},16 path::Path,17};1819use jrsonnet_evaluator::{20 trace::PathResolver, FileImportResolver, IStr, ManifestFormat, State, Val,21};222324#[cfg(target_arch = "wasm32")]25#[no_mangle]26pub extern "C" fn _start() {}2728293031#[no_mangle]32pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {33 b"v0.16.0\0"34}3536unsafe fn parse_path(input: &CStr) -> Cow<Path> {37 #[cfg(target_family = "unix")]38 {39 use std::os::unix::ffi::OsStrExt;40 let str = OsStr::from_bytes(input.to_bytes());41 Cow::Borrowed(Path::new(str))42 }43 #[cfg(target_family = "windows")]44 {45 use std::os::windows::ffi::OsStringExt;46 let str = input.to_str().expect("input is not utf8");47 let wide = str.encode_utf16().collect::<Vec<_>>();48 let wide = OsString::from_wide(&wide);49 Cow::Owned(PathBuf::new(wide))50 }51 #[cfg(not(any(target_family = "unix", target_family = "windows")))]52 {53 compile_error!("unsupported os")54 }55}5657unsafe fn unparse_path(input: &Path) -> Cow<CStr> {58 #[cfg(target_family = "unix")]59 {60 use std::os::unix::ffi::OsStrExt;61 let str = CString::new(input.as_os_str().as_bytes()).expect("input has zero byte in it");62 Cow::Owned(str)63 }64 #[cfg(not(any(target_family = "unix", target_family = "windows")))]65 {66 compile_error!("unsupported os")67 }68}697071#[no_mangle]72pub extern "C" fn jsonnet_make() -> *mut State {73 let state = State::default();74 state.settings_mut().import_resolver = Box::new(FileImportResolver::default());75 state.settings_mut().context_initializer = Box::new(jrsonnet_stdlib::ContextInitializer::new(76 state.clone(),77 PathResolver::new_cwd_fallback(),78 ));79 Box::into_raw(Box::new(state))80}818283#[no_mangle]84#[allow(clippy::boxed_local)]85pub extern "C" fn jsonnet_destroy(vm: Box<State>) {86 drop(vm);87}888990#[no_mangle]91pub extern "C" fn jsonnet_max_stack(vm: &State, v: c_uint) {92 vm.settings_mut().max_stack = v as usize;93}9495969798#[no_mangle]99pub extern "C" fn jsonnet_gc_min_objects(_vm: &State, _v: c_uint) {}100101102103104#[no_mangle]105pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &State, _v: c_double) {}106107108#[no_mangle]109pub extern "C" fn jsonnet_string_output(vm: &State, v: c_int) {110 match v {111 1 => vm.set_manifest_format(ManifestFormat::String),112 0 => vm.set_manifest_format(ManifestFormat::Json {113 padding: 4,114 #[cfg(feature = "exp-preserve-order")]115 preserve_order: false,116 }),117 _ => panic!("incorrect output format"),118 }119}120121122123124125126127128129#[no_mangle]130pub unsafe extern "C" fn jsonnet_realloc(_vm: &State, buf: *mut u8, sz: usize) -> *mut u8 {131 if buf.is_null() {132 if sz == 0 {133 return std::ptr::null_mut();134 }135 return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());136 }137 138 139 140 141 let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();142 if sz == 0 {143 std::alloc::dealloc(buf, old_layout);144 return std::ptr::null_mut();145 }146 std::alloc::realloc(buf, old_layout, sz)147}148149150151152#[no_mangle]153#[allow(clippy::boxed_local)]154pub extern "C" fn jsonnet_json_destroy(_vm: &State, v: Box<Val>) {155 drop(v);156}157158159#[no_mangle]160pub extern "C" fn jsonnet_max_trace(vm: &State, v: c_uint) {161 vm.set_max_trace(v as usize)162}163164165166167168169170171#[no_mangle]172pub unsafe extern "C" fn jsonnet_evaluate_file(173 vm: &State,174 filename: *const c_char,175 error: &mut c_int,176) -> *const c_char {177 let filename = parse_path(CStr::from_ptr(filename));178 match vm179 .import(&filename)180 .and_then(|v| vm.with_tla(v))181 .and_then(|v| vm.manifest(v))182 {183 Ok(v) => {184 *error = 0;185 CString::new(&*v as &str).unwrap().into_raw()186 }187 Err(e) => {188 *error = 1;189 let out = vm.stringify_err(&e);190 CString::new(&out as &str).unwrap().into_raw()191 }192 }193}194195196197198199200201202#[no_mangle]203pub unsafe extern "C" fn jsonnet_evaluate_snippet(204 vm: &State,205 filename: *const c_char,206 snippet: *const c_char,207 error: &mut c_int,208) -> *const c_char {209 let filename = CStr::from_ptr(filename);210 let snippet = CStr::from_ptr(snippet);211 match vm212 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())213 .and_then(|v| vm.with_tla(v))214 .and_then(|v| vm.manifest(v))215 {216 Ok(v) => {217 *error = 0;218 CString::new(&*v as &str).unwrap().into_raw()219 }220 Err(e) => {221 *error = 1;222 let out = vm.stringify_err(&e);223 CString::new(&out as &str).unwrap().into_raw()224 }225 }226}227228fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {229 let mut out = Vec::new();230 for (i, (k, v)) in multi.iter().enumerate() {231 if i != 0 {232 out.push(0);233 }234 out.extend_from_slice(k.as_bytes());235 out.push(0);236 out.extend_from_slice(v.as_bytes());237 }238 out.push(0);239 out.push(0);240 let v = out.as_ptr();241 std::mem::forget(out);242 v as *const c_char243}244245246#[no_mangle]247pub unsafe extern "C" fn jsonnet_evaluate_file_multi(248 vm: &State,249 filename: *const c_char,250 error: &mut c_int,251) -> *const c_char {252 let filename = parse_path(CStr::from_ptr(filename));253 match vm254 .import(&filename)255 .and_then(|v| vm.with_tla(v))256 .and_then(|v| vm.manifest_multi(v))257 {258 Ok(v) => {259 *error = 0;260 multi_to_raw(v)261 }262 Err(e) => {263 *error = 1;264 let out = vm.stringify_err(&e);265 CString::new(&out as &str).unwrap().into_raw()266 }267 }268}269270271#[no_mangle]272pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(273 vm: &State,274 filename: *const c_char,275 snippet: *const c_char,276 error: &mut c_int,277) -> *const c_char {278 let filename = CStr::from_ptr(filename);279 let snippet = CStr::from_ptr(snippet);280 match vm281 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())282 .and_then(|v| vm.with_tla(v))283 .and_then(|v| vm.manifest_multi(v))284 {285 Ok(v) => {286 *error = 0;287 multi_to_raw(v)288 }289 Err(e) => {290 *error = 1;291 let out = vm.stringify_err(&e);292 CString::new(&out as &str).unwrap().into_raw()293 }294 }295}296297fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {298 let mut out = Vec::new();299 for (i, v) in multi.iter().enumerate() {300 if i != 0 {301 out.push(0);302 }303 out.extend_from_slice(v.as_bytes());304 }305 out.push(0);306 out.push(0);307 let v = out.as_ptr();308 std::mem::forget(out);309 v as *const c_char310}311312313#[no_mangle]314pub unsafe extern "C" fn jsonnet_evaluate_file_stream(315 vm: &State,316 filename: *const c_char,317 error: &mut c_int,318) -> *const c_char {319 let filename = parse_path(CStr::from_ptr(filename));320 match vm321 .import(&filename)322 .and_then(|v| vm.with_tla(v))323 .and_then(|v| vm.manifest_stream(v))324 {325 Ok(v) => {326 *error = 0;327 stream_to_raw(v)328 }329 Err(e) => {330 *error = 1;331 let out = vm.stringify_err(&e);332 CString::new(&out as &str)333 .expect("there should be no \\0 in the error string")334 .into_raw()335 }336 }337}338339340#[no_mangle]341pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(342 vm: &State,343 filename: *const c_char,344 snippet: *const c_char,345 error: &mut c_int,346) -> *const c_char {347 let filename = CStr::from_ptr(filename);348 let snippet = CStr::from_ptr(snippet);349 match vm350 .evaluate_snippet(351 filename.to_str().expect("filename is not utf-8"),352 snippet.to_str().expect("snippet is not utf-8"),353 )354 .and_then(|v| vm.with_tla(v))355 .and_then(|v| vm.manifest_stream(v))356 {357 Ok(v) => {358 *error = 0;359 stream_to_raw(v)360 }361 Err(e) => {362 *error = 1;363 let out = vm.stringify_err(&e);364 CString::new(&out as &str)365 .expect("there should be no \\0 in the error string")366 .into_raw()367 }368 }369}