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() {}272829303132#[no_mangle]33pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {34 b"v0.16.0\0"35}3637unsafe fn parse_path(input: &CStr) -> Cow<Path> {38 #[cfg(target_family = "unix")]39 {40 use std::os::unix::ffi::OsStrExt;41 let str = OsStr::from_bytes(input.to_bytes());42 Cow::Borrowed(Path::new(str))43 }44 #[cfg(target_family = "windows")]45 {46 use std::os::windows::ffi::OsStringExt;47 let str = input.to_str().expect("input is not utf8");48 let wide = str.encode_utf16().collect::<Vec<_>>();49 let wide = OsString::from_wide(&wide);50 Cow::Owned(PathBuf::new(wide))51 }52 #[cfg(not(any(target_family = "unix", target_family = "windows")))]53 {54 compile_error!("unsupported os")55 }56}5758unsafe fn unparse_path(input: &Path) -> Cow<CStr> {59 #[cfg(target_family = "unix")]60 {61 use std::os::unix::ffi::OsStrExt;62 let str = CString::new(input.as_os_str().as_bytes()).expect("input has zero byte in it");63 Cow::Owned(str)64 }65 #[cfg(not(any(target_family = "unix", target_family = "windows")))]66 {67 compile_error!("unsupported os")68 }69}707172#[no_mangle]73pub extern "C" fn jsonnet_make() -> *mut State {74 let state = State::default();75 state.settings_mut().import_resolver = Box::new(FileImportResolver::default());76 state.settings_mut().context_initializer = Box::new(jrsonnet_stdlib::ContextInitializer::new(77 state.clone(),78 PathResolver::new_cwd_fallback(),79 ));80 Box::into_raw(Box::new(state))81}828384#[no_mangle]85#[allow(clippy::boxed_local)]86pub extern "C" fn jsonnet_destroy(vm: Box<State>) {87 drop(vm);88}899091#[no_mangle]92pub extern "C" fn jsonnet_max_stack(vm: &State, v: c_uint) {93 vm.settings_mut().max_stack = v as usize;94}9596979899#[no_mangle]100pub extern "C" fn jsonnet_gc_min_objects(_vm: &State, _v: c_uint) {}101102103104105#[no_mangle]106pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &State, _v: c_double) {}107108109#[no_mangle]110pub extern "C" fn jsonnet_string_output(vm: &State, v: c_int) {111 match v {112 1 => vm.set_manifest_format(ManifestFormat::String),113 0 => vm.set_manifest_format(ManifestFormat::Json {114 padding: 4,115 #[cfg(feature = "exp-preserve-order")]116 preserve_order: false,117 }),118 _ => panic!("incorrect output format"),119 }120}121122123124125126127128129130#[no_mangle]131pub unsafe extern "C" fn jsonnet_realloc(_vm: &State, buf: *mut u8, sz: usize) -> *mut u8 {132 if buf.is_null() {133 if sz == 0 {134 return std::ptr::null_mut();135 }136 return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());137 }138 139 140 141 142 let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();143 if sz == 0 {144 std::alloc::dealloc(buf, old_layout);145 return std::ptr::null_mut();146 }147 std::alloc::realloc(buf, old_layout, sz)148}149150151152153#[no_mangle]154#[allow(clippy::boxed_local)]155pub extern "C" fn jsonnet_json_destroy(_vm: &State, v: Box<Val>) {156 drop(v);157}158159160#[no_mangle]161pub extern "C" fn jsonnet_max_trace(vm: &State, v: c_uint) {162 vm.set_max_trace(v as usize)163}164165166167168169170171172#[no_mangle]173pub unsafe extern "C" fn jsonnet_evaluate_file(174 vm: &State,175 filename: *const c_char,176 error: &mut c_int,177) -> *const c_char {178 let filename = parse_path(CStr::from_ptr(filename));179 match vm180 .import(&filename)181 .and_then(|v| vm.with_tla(v))182 .and_then(|v| vm.manifest(v))183 {184 Ok(v) => {185 *error = 0;186 CString::new(&*v as &str).unwrap().into_raw()187 }188 Err(e) => {189 *error = 1;190 let out = vm.stringify_err(&e);191 CString::new(&out as &str).unwrap().into_raw()192 }193 }194}195196197198199200201202203#[no_mangle]204pub unsafe extern "C" fn jsonnet_evaluate_snippet(205 vm: &State,206 filename: *const c_char,207 snippet: *const c_char,208 error: &mut c_int,209) -> *const c_char {210 let filename = CStr::from_ptr(filename);211 let snippet = CStr::from_ptr(snippet);212 match vm213 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())214 .and_then(|v| vm.with_tla(v))215 .and_then(|v| vm.manifest(v))216 {217 Ok(v) => {218 *error = 0;219 CString::new(&*v as &str).unwrap().into_raw()220 }221 Err(e) => {222 *error = 1;223 let out = vm.stringify_err(&e);224 CString::new(&out as &str).unwrap().into_raw()225 }226 }227}228229fn multi_to_raw(multi: Vec<(IStr, IStr)>) -> *const c_char {230 let mut out = Vec::new();231 for (i, (k, v)) in multi.iter().enumerate() {232 if i != 0 {233 out.push(0);234 }235 out.extend_from_slice(k.as_bytes());236 out.push(0);237 out.extend_from_slice(v.as_bytes());238 }239 out.push(0);240 out.push(0);241 let v = out.as_ptr();242 std::mem::forget(out);243 v as *const c_char244}245246247#[no_mangle]248pub unsafe extern "C" fn jsonnet_evaluate_file_multi(249 vm: &State,250 filename: *const c_char,251 error: &mut c_int,252) -> *const c_char {253 let filename = parse_path(CStr::from_ptr(filename));254 match vm255 .import(&filename)256 .and_then(|v| vm.with_tla(v))257 .and_then(|v| vm.manifest_multi(v))258 {259 Ok(v) => {260 *error = 0;261 multi_to_raw(v)262 }263 Err(e) => {264 *error = 1;265 let out = vm.stringify_err(&e);266 CString::new(&out as &str).unwrap().into_raw()267 }268 }269}270271272#[no_mangle]273pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(274 vm: &State,275 filename: *const c_char,276 snippet: *const c_char,277 error: &mut c_int,278) -> *const c_char {279 let filename = CStr::from_ptr(filename);280 let snippet = CStr::from_ptr(snippet);281 match vm282 .evaluate_snippet(filename.to_str().unwrap(), snippet.to_str().unwrap())283 .and_then(|v| vm.with_tla(v))284 .and_then(|v| vm.manifest_multi(v))285 {286 Ok(v) => {287 *error = 0;288 multi_to_raw(v)289 }290 Err(e) => {291 *error = 1;292 let out = vm.stringify_err(&e);293 CString::new(&out as &str).unwrap().into_raw()294 }295 }296}297298fn stream_to_raw(multi: Vec<IStr>) -> *const c_char {299 let mut out = Vec::new();300 for (i, v) in multi.iter().enumerate() {301 if i != 0 {302 out.push(0);303 }304 out.extend_from_slice(v.as_bytes());305 }306 out.push(0);307 out.push(0);308 let v = out.as_ptr();309 std::mem::forget(out);310 v as *const c_char311}312313314#[no_mangle]315pub unsafe extern "C" fn jsonnet_evaluate_file_stream(316 vm: &State,317 filename: *const c_char,318 error: &mut c_int,319) -> *const c_char {320 let filename = parse_path(CStr::from_ptr(filename));321 match vm322 .import(&filename)323 .and_then(|v| vm.with_tla(v))324 .and_then(|v| vm.manifest_stream(v))325 {326 Ok(v) => {327 *error = 0;328 stream_to_raw(v)329 }330 Err(e) => {331 *error = 1;332 let out = vm.stringify_err(&e);333 CString::new(&out as &str)334 .expect("there should be no \\0 in the error string")335 .into_raw()336 }337 }338}339340341#[no_mangle]342pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(343 vm: &State,344 filename: *const c_char,345 snippet: *const c_char,346 error: &mut c_int,347) -> *const c_char {348 let filename = CStr::from_ptr(filename);349 let snippet = CStr::from_ptr(snippet);350 match vm351 .evaluate_snippet(352 filename.to_str().expect("filename is not utf-8"),353 snippet.to_str().expect("snippet is not utf-8"),354 )355 .and_then(|v| vm.with_tla(v))356 .and_then(|v| vm.manifest_stream(v))357 {358 Ok(v) => {359 *error = 0;360 stream_to_raw(v)361 }362 Err(e) => {363 *error = 1;364 let out = vm.stringify_err(&e);365 CString::new(&out as &str)366 .expect("there should be no \\0 in the error string")367 .into_raw()368 }369 }370}