git.delta.rocks / jrsonnet / refs/commits / 2c8a29e649b8

difftreelog

feat(bindings) object append

Лач2020-06-28parent: #27ecbf0.patch.diff
in: master

1 file changed

modifiedbindings/jsonnet/src/lib.rsdiffbeforeafterboth
before · bindings/jsonnet/src/lib.rs
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}7071// TODO72#[no_mangle]73pub extern "C" fn jsonnet_max_stack(_vm: &EvaluationState, _v: c_uint) {}7475// jrsonnet currently have no GC, so these functions is no-op76#[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) {}8081// TODO82#[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}121122/// # Safety123///124/// This function is safe, if received v is a pointer to normal C string125#[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/// # Safety185///186/// This function is most definitely broken, but it works somehow, see TODO inside187#[no_mangle]188pub unsafe extern "C" fn jsonnet_realloc(189	_vm: &EvaluationState,190	buf: *mut u8,191	sz: usize,192) -> *mut u8 {193	if buf.is_null() {194		assert!(sz != 0);195		return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());196	}197	// TODO: Somehow store size of allocation, because its real size is probally not 16 :D198	// OR (Alternative way of fixing this TODO)199	// TODO: Standard allocator uses malloc, and it doesn't uses allocation size,200	// TODO: so it should work in normal cases. Maybe force allocator for this library?201	let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();202	if sz == 0 {203		std::alloc::dealloc(buf, old_layout);204		return std::ptr::null_mut();205	}206	std::alloc::realloc(buf, old_layout, sz)207}208209#[no_mangle]210#[allow(clippy::boxed_local)]211pub extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, _v: Box<Val>) {}212213#[no_mangle]214pub extern "C" fn jsonnet_import_callback() {215	todo!()216}217#[no_mangle]218pub extern "C" fn jsonnet_native_callback() {219	todo!()220}221#[no_mangle]222pub extern "C" fn jsonnet_ext_var() {223	todo!()224}225#[no_mangle]226pub extern "C" fn jsonnet_ext_code() {227	todo!()228}229#[no_mangle]230pub extern "C" fn jsonnet_tla_var() {231	todo!()232}233#[no_mangle]234pub extern "C" fn jsonnet_tla_code() {235	todo!()236}237#[no_mangle]238pub extern "C" fn jsonnet_max_trace() {239	todo!()240}241242/// # Safety243///244/// This function is safe, if received v is a pointer to normal C string245#[no_mangle]246pub unsafe extern "C" fn jsonnet_jpath_add(vm: &EvaluationState, v: *const c_char) {247	let cstr = CStr::from_ptr(v);248	let path = PathBuf::from(cstr.to_str().unwrap());249	let any_resolver = vm.import_resolver();250	let resolver = any_resolver251		.as_any()252		.downcast_ref::<NativeImportResolver>()253		.unwrap();254	resolver.add_jpath(path);255}256257/// # Safety258///259/// This function is safe, if received v is a pointer to normal C string260#[no_mangle]261pub unsafe extern "C" fn jsonnet_evaluate_file(262	vm: &EvaluationState,263	filename: *const c_char,264	error: &mut c_int,265) -> *const c_char {266	vm.run_in_state(|| {267		use std::fmt::Write;268		let filename = CStr::from_ptr(filename);269		match vm.evaluate_file_to_json(&PathBuf::from(filename.to_str().unwrap())) {270			Ok(v) => {271				*error = 0;272				CString::new(&*v as &str).unwrap().into_raw()273			}274			Err(e) => {275				*error = 1;276				let mut out = String::new();277				writeln!(out, "{:?}", e.0).unwrap();278				for i in (e.1).0.iter() {279					writeln!(out, "{:?}", i).unwrap();280				}281				CString::new(&out as &str).unwrap().into_raw()282			}283		}284	})285}286#[no_mangle]287pub extern "C" fn jsonnet_evaluate_snippet() {288	todo!()289}290#[no_mangle]291pub extern "C" fn jsonnet_evaluate_file_multi() {292	todo!()293}294#[no_mangle]295pub extern "C" fn jsonnet_evaluate_snippet_multi() {296	todo!()297}298#[no_mangle]299pub extern "C" fn jsonnet_evaluate_file_stream() {300	todo!()301}302#[no_mangle]303pub extern "C" fn jsonnet_evaluate_snippet_stream() {304	todo!()305}306307#[no_mangle]308#[allow(clippy::boxed_local)]309pub extern "C" fn jsonnet_destroy(_vm: Box<EvaluationState>) {}
after · bindings/jsonnet/src/lib.rs
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}7071// TODO72#[no_mangle]73pub extern "C" fn jsonnet_max_stack(_vm: &EvaluationState, _v: c_uint) {}7475// jrsonnet currently have no GC, so these functions is no-op76#[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) {}8081// TODO82#[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}121122/// # Safety123///124/// This function is safe, if received v is a pointer to normal C string125#[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			// TODO: Mutate array, instead of recreating them161			let mut new = Vec::new();162			new.extend(old.iter().cloned());163			new.push(val.clone());164			*arr = Val::Arr(Rc::new(new));165		}166		_ => panic!("should receive array"),167	}168}169170#[no_mangle]171pub extern "C" fn jsonnet_json_make_object(_vm: &EvaluationState) -> Box<Val> {172	Box::new(Val::Obj(ObjValue::new_empty()))173}174175/// # Safety176///177/// This function is safe if passed name is ok178#[no_mangle]179pub unsafe extern "C" fn jsonnet_json_object_append(180	_vm: &EvaluationState,181	obj: &mut Val,182	name: *const c_char,183	val: &Val,184) {185	match obj {186		Val::Obj(old) => {187			let mut new = BTreeMap::new();188			new.insert(189				CStr::from_ptr(name).to_str().unwrap().into(),190				ObjMember {191					add: false,192					visibility: Visibility::Normal,193					invoke: LazyBinding::Bound(LazyVal::new_resolved(val.clone())),194				},195			);196			let new_obj = ObjValue::new(Some(old.clone()), Rc::new(new));197			*obj = Val::Obj(new_obj);198		}199		_ => panic!("should receive array"),200	}201}202203/// # Safety204///205/// This function is most definitely broken, but it works somehow, see TODO inside206#[no_mangle]207pub unsafe extern "C" fn jsonnet_realloc(208	_vm: &EvaluationState,209	buf: *mut u8,210	sz: usize,211) -> *mut u8 {212	if buf.is_null() {213		assert!(sz != 0);214		return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());215	}216	// TODO: Somehow store size of allocation, because its real size is probally not 16 :D217	// OR (Alternative way of fixing this TODO)218	// TODO: Standard allocator uses malloc, and it doesn't uses allocation size,219	// TODO: so it should work in normal cases. Maybe force allocator for this library?220	let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();221	if sz == 0 {222		std::alloc::dealloc(buf, old_layout);223		return std::ptr::null_mut();224	}225	std::alloc::realloc(buf, old_layout, sz)226}227228#[no_mangle]229#[allow(clippy::boxed_local)]230pub extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, _v: Box<Val>) {}231232#[no_mangle]233pub extern "C" fn jsonnet_import_callback() {234	todo!()235}236#[no_mangle]237pub extern "C" fn jsonnet_native_callback() {238	todo!()239}240#[no_mangle]241pub extern "C" fn jsonnet_ext_var() {242	todo!()243}244#[no_mangle]245pub extern "C" fn jsonnet_ext_code() {246	todo!()247}248#[no_mangle]249pub extern "C" fn jsonnet_tla_var() {250	todo!()251}252#[no_mangle]253pub extern "C" fn jsonnet_tla_code() {254	todo!()255}256#[no_mangle]257pub extern "C" fn jsonnet_max_trace() {258	todo!()259}260261/// # Safety262///263/// This function is safe, if received v is a pointer to normal C string264#[no_mangle]265pub unsafe extern "C" fn jsonnet_jpath_add(vm: &EvaluationState, v: *const c_char) {266	let cstr = CStr::from_ptr(v);267	let path = PathBuf::from(cstr.to_str().unwrap());268	let any_resolver = vm.import_resolver();269	let resolver = any_resolver270		.as_any()271		.downcast_ref::<NativeImportResolver>()272		.unwrap();273	resolver.add_jpath(path);274}275276/// # Safety277///278/// This function is safe, if received v is a pointer to normal C string279#[no_mangle]280pub unsafe extern "C" fn jsonnet_evaluate_file(281	vm: &EvaluationState,282	filename: *const c_char,283	error: &mut c_int,284) -> *const c_char {285	vm.run_in_state(|| {286		use std::fmt::Write;287		let filename = CStr::from_ptr(filename);288		match vm.evaluate_file_to_json(&PathBuf::from(filename.to_str().unwrap())) {289			Ok(v) => {290				*error = 0;291				CString::new(&*v as &str).unwrap().into_raw()292			}293			Err(e) => {294				*error = 1;295				let mut out = String::new();296				writeln!(out, "{:?}", e.0).unwrap();297				for i in (e.1).0.iter() {298					writeln!(out, "{:?}", i).unwrap();299				}300				CString::new(&out as &str).unwrap().into_raw()301			}302		}303	})304}305#[no_mangle]306pub extern "C" fn jsonnet_evaluate_snippet() {307	todo!()308}309#[no_mangle]310pub extern "C" fn jsonnet_evaluate_file_multi() {311	todo!()312}313#[no_mangle]314pub extern "C" fn jsonnet_evaluate_snippet_multi() {315	todo!()316}317#[no_mangle]318pub extern "C" fn jsonnet_evaluate_file_stream() {319	todo!()320}321#[no_mangle]322pub extern "C" fn jsonnet_evaluate_snippet_stream() {323	todo!()324}325326#[no_mangle]327#[allow(clippy::boxed_local)]328pub extern "C" fn jsonnet_destroy(_vm: Box<EvaluationState>) {}