git.delta.rocks / jrsonnet / refs/commits / 6e40dd49aa72

difftreelog

feat multi and stream manifests

Lach2020-08-23parent: #020afa6.patch.diff
in: master

5 files changed

modifiedbindings/jsonnet/src/lib.rsdiffbeforeafterboth
before · bindings/jsonnet/src/lib.rs
1pub mod import;2pub mod interop;3pub mod native;4pub mod val_extract;5pub mod val_make;6pub mod val_modify;7pub mod vars_tlas;89use import::NativeImportResolver;10use jrsonnet_evaluator::{EvaluationState, ManifestFormat, Val};11use std::{12	alloc::Layout,13	ffi::{CStr, CString},14	os::raw::{c_char, c_double, c_int, c_uint},15	path::PathBuf,16	rc::Rc,17};1819/// WASM stub20#[cfg(target_arch = "wasm32")]21#[no_mangle]22pub extern "C" fn _start() {}2324#[no_mangle]25pub extern "C" fn jsonnet_version() -> &'static [u8; 8] {26	b"v0.16.0\0"27}2829#[no_mangle]30pub extern "C" fn jsonnet_make() -> *mut EvaluationState {31	let state = EvaluationState::default();32	state.with_stdlib();33	state.settings_mut().import_resolver = Box::new(NativeImportResolver::default());34	Box::into_raw(Box::new(state))35}3637/// # Safety38#[no_mangle]39#[allow(clippy::boxed_local)]40pub unsafe extern "C" fn jsonnet_destroy(vm: *mut EvaluationState) {41	Box::from_raw(vm);42}4344#[no_mangle]45pub extern "C" fn jsonnet_max_stack(vm: &EvaluationState, v: c_uint) {46	vm.settings_mut().max_stack = v as usize;47}4849// jrsonnet currently have no GC, so these functions is no-op50#[no_mangle]51pub extern "C" fn jsonnet_gc_min_objects(_vm: &EvaluationState, _v: c_uint) {}52#[no_mangle]53pub extern "C" fn jsonnet_gc_growth_trigger(_vm: &EvaluationState, _v: c_double) {}5455#[no_mangle]56pub extern "C" fn jsonnet_string_output(vm: &EvaluationState, v: c_int) {57	match v {58		1 => vm.set_manifest_format(ManifestFormat::String),59		0 => vm.set_manifest_format(ManifestFormat::Json(4)),60		_ => panic!("incorrect output format"),61	}62}6364/// # Safety65///66/// This function is most definitely broken, but it works somehow, see TODO inside67#[no_mangle]68pub unsafe extern "C" fn jsonnet_realloc(69	_vm: &EvaluationState,70	buf: *mut u8,71	sz: usize,72) -> *mut u8 {73	if buf.is_null() {74		assert!(sz != 0);75		return std::alloc::alloc(Layout::from_size_align(sz, std::mem::align_of::<u8>()).unwrap());76	}77	// TODO: Somehow store size of allocation, because its real size is probally not 16 :D78	// OR (Alternative way of fixing this TODO)79	// TODO: Standard allocator uses malloc, and it doesn't uses allocation size,80	// TODO: so it should work in normal cases. Maybe force allocator for this library?81	let old_layout = Layout::from_size_align(16, std::mem::align_of::<u8>()).unwrap();82	if sz == 0 {83		std::alloc::dealloc(buf, old_layout);84		return std::ptr::null_mut();85	}86	std::alloc::realloc(buf, old_layout, sz)87}8889/// # Safety90#[no_mangle]91#[allow(clippy::boxed_local)]92pub unsafe extern "C" fn jsonnet_json_destroy(_vm: &EvaluationState, v: *mut Val) {93	Box::from_raw(v);94}9596#[no_mangle]97pub extern "C" fn jsonnet_max_trace(vm: &EvaluationState, v: c_uint) {98	vm.set_max_trace(v as usize)99}100101/// # Safety102///103/// This function is safe, if received v is a pointer to normal C string104#[no_mangle]105pub unsafe extern "C" fn jsonnet_evaluate_file(106	vm: &EvaluationState,107	filename: *const c_char,108	error: &mut c_int,109) -> *const c_char {110	vm.run_in_state(|| {111		let filename = CStr::from_ptr(filename);112		match vm113			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))114			.and_then(|v| vm.with_tla(v))115			.and_then(|v| vm.manifest(v))116		{117			Ok(v) => {118				*error = 0;119				CString::new(&*v as &str).unwrap().into_raw()120			}121			Err(e) => {122				*error = 1;123				let out = vm.stringify_err(&e);124				CString::new(&out as &str).unwrap().into_raw()125			}126		}127	})128}129130/// # Safety131///132/// This function is safe, if received v is a pointer to normal C string133#[no_mangle]134pub unsafe extern "C" fn jsonnet_evaluate_snippet(135	vm: &EvaluationState,136	filename: *const c_char,137	snippet: *const c_char,138	error: &mut c_int,139) -> *const c_char {140	vm.run_in_state(|| {141		let filename = CStr::from_ptr(filename);142		let snippet = CStr::from_ptr(snippet);143		match vm144			.evaluate_snippet_raw(145				Rc::new(PathBuf::from(filename.to_str().unwrap())),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	})162}163164#[no_mangle]165pub extern "C" fn jsonnet_evaluate_file_multi() {166	todo!()167}168#[no_mangle]169pub extern "C" fn jsonnet_evaluate_snippet_multi() {170	todo!()171}172#[no_mangle]173pub extern "C" fn jsonnet_evaluate_file_stream() {174	todo!()175}176#[no_mangle]177pub extern "C" fn jsonnet_evaluate_snippet_stream() {178	todo!()179}
modifiedcrates/jrsonnet-evaluator/src/builtin/format.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/builtin/format.rs
+++ b/crates/jrsonnet-evaluator/src/builtin/format.rs
@@ -470,7 +470,7 @@
 	let mut tmp_out = String::new();
 
 	match code.convtype {
-		ConvTypeV::String => tmp_out.push_str(&value.clone().into_string()?),
+		ConvTypeV::String => tmp_out.push_str(&value.clone().to_string()?),
 		ConvTypeV::Decimal => {
 			let value = value.clone().try_cast_num("%d/%u/%i requires number")?;
 			render_decimal(
modifiedcrates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/evaluate.rs
+++ b/crates/jrsonnet-evaluator/src/evaluate.rs
@@ -95,8 +95,8 @@
 		(Val::Num(n), Val::Str(o)) => Val::Str(format!("{}{}", n, o).into()),
 		(Val::Str(o), Val::Num(n)) => Val::Str(format!("{}{}", o, n).into()),
 
-		(Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().into_string()?).into()),
-		(o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().into_string()?, s).into()),
+		(Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().to_string()?).into()),
+		(o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().to_string()?, s).into()),
 
 		(Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),
 		(Val::Arr(a), Val::Arr(b)) => Val::Arr(Rc::new([&a[..], &b[..]].concat())),
@@ -975,9 +975,9 @@
 			if assertion_result {
 				evaluate(context, returned)?
 			} else if let Some(msg) = msg {
-				throw!(AssertionFailed(evaluate(context, msg)?));
+				throw!(AssertionFailed(evaluate(context, msg)?.to_string()?));
 			} else {
-				throw!(AssertionFailed(Val::Null));
+				throw!(AssertionFailed(Val::Null.to_string()?));
 			}
 		}
 		ErrorStmt(e) => push(
modifiedcrates/jrsonnet-evaluator/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/lib.rs
+++ b/crates/jrsonnet-evaluator/src/lib.rs
@@ -321,6 +321,12 @@
 	pub fn manifest(&self, val: Val) -> Result<Rc<str>> {
 		self.run_in_state(|| val.manifest(&self.manifest_format()))
 	}
+	pub fn manifest_multi(&self, val: Val) -> Result<Vec<(Rc<str>, Rc<str>)>> {
+		self.run_in_state(|| val.manifest_multi(&self.manifest_format()))
+	}
+	pub fn manifest_stream(&self, val: Val) -> Result<Vec<Rc<str>>> {
+		self.run_in_state(|| val.manifest_stream(&self.manifest_format()))
+	}
 
 	/// If passed value is function - call with set TLA
 	pub fn with_tla(&self, val: Val) -> Result<Val> {
modifiedcrates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -213,7 +213,7 @@
 		})
 	}
 
-	pub fn into_string(self) -> Result<Rc<str>> {
+	pub fn to_string(&self) -> Result<Rc<str>> {
 		Ok(match self.unwrap_if_lazy()? {
 			Val::Bool(true) => "true".into(),
 			Val::Bool(false) => "false".into(),
@@ -230,6 +230,36 @@
 		})
 	}
 
+	/// Expects value to be object, outputs (key, manifested value) pairs
+	pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(Rc<str>, Rc<str>)>> {
+		let obj = match self {
+			Val::Obj(obj) => obj,
+			_ => throw!(MultiManifestOutputIsNotAObject),
+		};
+		let keys = obj.visible_fields();
+		let mut out = Vec::with_capacity(keys.len());
+		for key in keys {
+			let value = obj
+				.get(key.clone())?
+				.expect("item in object")
+				.manifest(ty)?;
+			out.push((key, value));
+		}
+		Ok(out)
+	}
+
+	/// Expects value to be array, outputs manifested values
+	pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<Rc<str>>> {
+		let arr = match self {
+			Val::Arr(a) => a,
+			_ => throw!(StreamManifestOutputIsNotAArray),
+		};
+		let mut out = Vec::with_capacity(arr.len());
+		for i in arr.iter() {
+			out.push(i.manifest(ty)?);
+		}
+		Ok(out)
+	}
 
 	pub fn manifest(&self, ty: &ManifestFormat) -> Result<Rc<str>> {
 		Ok(match ty {