1use jrsonnet_evaluator::{2 create_error, create_error_result, Error, EvaluationState, ImportResolver, LazyBinding,3 LazyVal, ObjMember, ObjValue, Result, Val,4};5use jrsonnet_parser::Visibility;6use libc::{c_char, c_double, c_int, c_uint};7use std::{8 alloc::Layout,9 any::Any,10 cell::RefCell,11 collections::BTreeMap,12 ffi::{CStr, CString},13 fs::File,14 io::Read,15 path::PathBuf,16 rc::Rc,17};1819#[no_mangle]20pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {21 b"v0.16.0\0"22}2324#[derive(Default)]25struct NativeImportResolver {26 library_paths: RefCell<Vec<PathBuf>>,27}28impl NativeImportResolver {29 fn add_jpath(&self, path: PathBuf) {30 self.library_paths.borrow_mut().push(path);31 }32}33impl ImportResolver for NativeImportResolver {34 fn resolve_file(&self, from: &PathBuf, path: &PathBuf) -> Result<Rc<PathBuf>> {35 let mut new_path = from.clone();36 new_path.push(path);37 if new_path.exists() {38 Ok(Rc::new(new_path))39 } else {40 for library_path in self.library_paths.borrow().iter() {41 let mut cloned = library_path.clone();42 cloned.push(path);43 if cloned.exists() {44 return Ok(Rc::new(cloned));45 }46 }47 create_error_result(Error::ImportFileNotFound(from.clone(), path.clone()))48 }49 }50 fn load_file_contents(&self, id: &PathBuf) -> Result<Rc<str>> {51 let mut file =52 File::open(id).map_err(|_e| create_error(Error::ResolvedFileNotFound(id.clone())))?;53 let mut out = String::new();54 file.read_to_string(&mut out)55 .map_err(|_e| create_error(Error::ImportBadFileUtf8(id.clone())))?;56 Ok(out.into())57 }58 unsafe fn as_any(&self) -> &dyn Any {59 self60 }61}6263#[no_mangle]64pub extern "C" fn jsonnet_make() -> Box<EvaluationState> {65 let state = EvaluationState::default();66 state.with_stdlib();67 state.set_import_resolver(Box::new(NativeImportResolver::default()));68 Box::new(state)69}707172#[no_mangle]73pub extern "C" fn jsonnet_max_stack(_vm: &EvaluationState, _v: c_uint) {}747576#[no_mangle]77pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}78#[no_mangle]79pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}808182#[no_mangle]83pub extern "C" fn jsonnet_string_output(_vm: &EvaluationState, _v: c_int) {}8485#[no_mangle]86pub extern "C" fn jsonnet_json_extract_string(_vm: &EvaluationState, v: &Val) -> *mut c_char {87 match v.unwrap_if_lazy().unwrap() {88 Val::Str(s) => CString::new(&*s as &str).unwrap().into_raw(),89 _ => std::ptr::null_mut(),90 }91}92#[no_mangle]93pub extern "C" fn jsonnet_json_extract_number(94 _vm: &EvaluationState,95 v: &Val,96 out: &mut c_double,97) -> c_int {98 match v.unwrap_if_lazy().unwrap() {99 Val::Num(n) => {100 *out = n;101 1102 }103 _ => 0,104 }105}106#[no_mangle]107pub extern "C" fn jsonnet_json_extract_bool(_vm: &EvaluationState, v: &Val) -> c_int {108 match v.unwrap_if_lazy().unwrap() {109 Val::Bool(false) => 0,110 Val::Bool(true) => 1,111 _ => 2,112 }113}114#[no_mangle]115pub extern "C" fn jsonnet_json_extract_null(_vm: &EvaluationState, v: &Val) -> c_int {116 match v.unwrap_if_lazy().unwrap() {117 Val::Null => 1,118 _ => 0,119 }120}121122123124125#[no_mangle]126pub unsafe extern "C" fn jsonnet_json_make_string(127 _vm: &EvaluationState,128 v: *const c_char,129) -> Box<Val> {130 let cstr = CStr::from_ptr(v);131 let str = cstr.to_str().unwrap();132 Box::new(Val::Str(str.into()))133}134135#[no_mangle]136pub extern "C" fn jsonnet_json_make_number(_vm: &EvaluationState, v: c_double) -> Box<Val> {137 Box::new(Val::Num(v))138}139140#[no_mangle]141pub extern "C" fn jsonnet_json_make_bool(_vm: &EvaluationState, v: c_int) -> Box<Val> {142 assert!(v == 0 || v == 1);143 Box::new(Val::Bool(v == 1))144}145146#[no_mangle]147pub extern "C" fn jsonnet_json_make_null(_vm: &EvaluationState) -> Box<Val> {148 Box::new(Val::Null)149}150151#[no_mangle]152pub extern "C" fn jsonnet_json_make_array(_vm: &EvaluationState) -> Box<Val> {153 Box::new(Val::Arr(Rc::new(Vec::new())))154}155156#[no_mangle]157pub extern "C" fn jsonnet_json_array_append(_vm: &EvaluationState, arr: &mut Val, val: &Val) {158 match arr {159 Val::Arr(old) => {160 let mut new = Vec::new();161 new.extend(old.iter().cloned());162 new.push(val.clone());163 *arr = Val::Arr(Rc::new(new));164 }165 _ => panic!("should receive array"),166 }167}168169#[no_mangle]170pub extern "C" fn jsonnet_json_make_object(_vm: &EvaluationState) -> Box<Val> {171 Box::new(Val::Obj(ObjValue::new_empty()))172}173174#[no_mangle]175pub extern "C" fn jsonnet_json_object_append(176 _vm: &EvaluationState,177 _obj: &mut Val,178 _name: *const c_char,179 _val: &Val,180) {181 todo!()182}183184#[no_mangle]185pub extern "C" fn jsonnet_realloc(_vm: &EvaluationState, _buf: *const u8, _sz: usize) -> *const u8 {186 todo!()187}188189#[no_mangle]190#[allow(clippy::boxed_local)]191pub extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, _v: Box<Val>) {}192193#[no_mangle]194pub extern "C" fn jsonnet_import_callback() {195 todo!()196}197#[no_mangle]198pub extern "C" fn jsonnet_native_callback() {199 todo!()200}201#[no_mangle]202pub extern "C" fn jsonnet_ext_var() {203 todo!()204}205#[no_mangle]206pub extern "C" fn jsonnet_ext_code() {207 todo!()208}209#[no_mangle]210pub extern "C" fn jsonnet_tla_var() {211 todo!()212}213#[no_mangle]214pub extern "C" fn jsonnet_tla_code() {215 todo!()216}217#[no_mangle]218pub extern "C" fn jsonnet_max_trace() {219 todo!()220}221222223224225#[no_mangle]226pub unsafe extern "C" fn jsonnet_jpath_add(vm: &EvaluationState, v: *const c_char) {227 let cstr = CStr::from_ptr(v);228 let path = PathBuf::from(cstr.to_str().unwrap());229 let any_resolver = vm.import_resolver();230 let resolver = any_resolver231 .as_any()232 .downcast_ref::<NativeImportResolver>()233 .unwrap();234 resolver.add_jpath(path);235}236237238239240#[no_mangle]241pub unsafe extern "C" fn jsonnet_evaluate_file(242 vm: &EvaluationState,243 filename: *const c_char,244 error: &mut c_int,245) -> *const c_char {246 vm.run_in_state(|| {247 use std::fmt::Write;248 let filename = CStr::from_ptr(filename);249 match vm.evaluate_file_to_json(&PathBuf::from(filename.to_str().unwrap())) {250 Ok(v) => {251 *error = 0;252 CString::new(&*v as &str).unwrap().into_raw()253 }254 Err(e) => {255 *error = 1;256 let mut out = String::new();257 writeln!(out, "{:?}", e.0).unwrap();258 for i in (e.1).0.iter() {259 writeln!(out, "{:?}", i).unwrap();260 }261 CString::new(&out as &str).unwrap().into_raw()262 }263 }264 })265}266#[no_mangle]267pub extern "C" fn jsonnet_evaluate_snippet() {268 todo!()269}270#[no_mangle]271pub extern "C" fn jsonnet_evaluate_file_multi() {272 todo!()273}274#[no_mangle]275pub extern "C" fn jsonnet_evaluate_snippet_multi() {276 todo!()277}278#[no_mangle]279pub extern "C" fn jsonnet_evaluate_file_stream() {280 todo!()281}282#[no_mangle]283pub extern "C" fn jsonnet_evaluate_snippet_stream() {284 todo!()285}286287#[no_mangle]288#[allow(clippy::boxed_local)]289pub extern "C" fn jsonnet_destroy(_vm: Box<EvaluationState>) {}