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
--- a/bindings/jsonnet/src/lib.rs
+++ b/bindings/jsonnet/src/lib.rs
@@ -161,19 +161,152 @@
 	})
 }
 
+fn multi_to_raw(multi: Vec<(Rc<str>, Rc<str>)>) -> *const c_char {
+	let mut out = Vec::new();
+	for (i, (k, v)) in multi.iter().enumerate() {
+		if i != 0 {
+			out.push(0);
+		}
+		out.extend_from_slice(k.as_bytes());
+		out.push(0);
+		out.extend_from_slice(v.as_bytes());
+	}
+	out.push(0);
+	out.push(0);
+	let v = out.as_ptr();
+	std::mem::forget(out);
+	v as *const c_char
+}
+
+/// # Safety
 #[no_mangle]
-pub extern "C" fn jsonnet_evaluate_file_multi() {
-	todo!()
+pub unsafe extern "C" fn jsonnet_evaluate_file_multi(
+	vm: &EvaluationState,
+	filename: *const c_char,
+	error: &mut c_int,
+) -> *const c_char {
+	vm.run_in_state(|| {
+		let filename = CStr::from_ptr(filename);
+		match vm
+			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))
+			.and_then(|v| vm.with_tla(v))
+			.and_then(|v| vm.manifest_multi(v))
+		{
+			Ok(v) => {
+				*error = 0;
+				multi_to_raw(v)
+			}
+			Err(e) => {
+				*error = 1;
+				let out = vm.stringify_err(&e);
+				CString::new(&out as &str).unwrap().into_raw()
+			}
+		}
+	})
 }
+
+/// # Safety
 #[no_mangle]
-pub extern "C" fn jsonnet_evaluate_snippet_multi() {
-	todo!()
+pub unsafe extern "C" fn jsonnet_evaluate_snippet_multi(
+	vm: &EvaluationState,
+	filename: *const c_char,
+	snippet: *const c_char,
+	error: &mut c_int,
+) -> *const c_char {
+	vm.run_in_state(|| {
+		let filename = CStr::from_ptr(filename);
+		let snippet = CStr::from_ptr(snippet);
+		match vm
+			.evaluate_snippet_raw(
+				Rc::new(PathBuf::from(filename.to_str().unwrap())),
+				snippet.to_str().unwrap().into(),
+			)
+			.and_then(|v| vm.with_tla(v))
+			.and_then(|v| vm.manifest_multi(v))
+		{
+			Ok(v) => {
+				*error = 0;
+				multi_to_raw(v)
+			}
+			Err(e) => {
+				*error = 1;
+				let out = vm.stringify_err(&e);
+				CString::new(&out as &str).unwrap().into_raw()
+			}
+		}
+	})
 }
+
+fn stream_to_raw(multi: Vec<Rc<str>>) -> *const c_char {
+	let mut out = Vec::new();
+	for (i, v) in multi.iter().enumerate() {
+		if i != 0 {
+			out.push(0);
+		}
+		out.extend_from_slice(v.as_bytes());
+	}
+	out.push(0);
+	out.push(0);
+	let v = out.as_ptr();
+	std::mem::forget(out);
+	v as *const c_char
+}
+
+/// # Safety
 #[no_mangle]
-pub extern "C" fn jsonnet_evaluate_file_stream() {
-	todo!()
+pub unsafe extern "C" fn jsonnet_evaluate_file_stream(
+	vm: &EvaluationState,
+	filename: *const c_char,
+	error: &mut c_int,
+) -> *const c_char {
+	vm.run_in_state(|| {
+		let filename = CStr::from_ptr(filename);
+		match vm
+			.evaluate_file_raw_nocwd(&PathBuf::from(filename.to_str().unwrap()))
+			.and_then(|v| vm.with_tla(v))
+			.and_then(|v| vm.manifest_stream(v))
+		{
+			Ok(v) => {
+				*error = 0;
+				stream_to_raw(v)
+			}
+			Err(e) => {
+				*error = 1;
+				let out = vm.stringify_err(&e);
+				CString::new(&out as &str).unwrap().into_raw()
+			}
+		}
+	})
 }
+
+/// # Safety
 #[no_mangle]
-pub extern "C" fn jsonnet_evaluate_snippet_stream() {
-	todo!()
+pub unsafe extern "C" fn jsonnet_evaluate_snippet_stream(
+	vm: &EvaluationState,
+	filename: *const c_char,
+	snippet: *const c_char,
+	error: &mut c_int,
+) -> *const c_char {
+	vm.run_in_state(|| {
+		let filename = CStr::from_ptr(filename);
+		let snippet = CStr::from_ptr(snippet);
+		match vm
+			.evaluate_snippet_raw(
+				Rc::new(PathBuf::from(filename.to_str().unwrap())),
+				snippet.to_str().unwrap().into(),
+			)
+			.and_then(|v| vm.with_tla(v))
+			.and_then(|v| vm.manifest_stream(v))
+		{
+			Ok(v) => {
+				*error = 0;
+				stream_to_raw(v)
+			}
+			Err(e) => {
+				*error = 1;
+				let out = vm.stringify_err(&e);
+				CString::new(&out as &str).unwrap().into_raw()
+			}
+		}
+	})
 }
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
213 })213 })
214 }214 }
215215
216 pub fn into_string(self) -> Result<Rc<str>> {216 pub fn to_string(&self) -> Result<Rc<str>> {
217 Ok(match self.unwrap_if_lazy()? {217 Ok(match self.unwrap_if_lazy()? {
218 Val::Bool(true) => "true".into(),218 Val::Bool(true) => "true".into(),
219 Val::Bool(false) => "false".into(),219 Val::Bool(false) => "false".into(),
230 })230 })
231 }231 }
232232
233 /// Expects value to be object, outputs (key, manifested value) pairs
234 pub fn manifest_multi(&self, ty: &ManifestFormat) -> Result<Vec<(Rc<str>, Rc<str>)>> {
235 let obj = match self {
236 Val::Obj(obj) => obj,
237 _ => throw!(MultiManifestOutputIsNotAObject),
238 };
239 let keys = obj.visible_fields();
240 let mut out = Vec::with_capacity(keys.len());
241 for key in keys {
242 let value = obj
243 .get(key.clone())?
244 .expect("item in object")
245 .manifest(ty)?;
246 out.push((key, value));
247 }
248 Ok(out)
249 }
250
251 /// Expects value to be array, outputs manifested values
252 pub fn manifest_stream(&self, ty: &ManifestFormat) -> Result<Vec<Rc<str>>> {
253 let arr = match self {
254 Val::Arr(a) => a,
255 _ => throw!(StreamManifestOutputIsNotAArray),
256 };
257 let mut out = Vec::with_capacity(arr.len());
258 for i in arr.iter() {
259 out.push(i.manifest(ty)?);
260 }
261 Ok(out)
262 }
233263
234 pub fn manifest(&self, ty: &ManifestFormat) -> Result<Rc<str>> {264 pub fn manifest(&self, ty: &ManifestFormat) -> Result<Rc<str>> {
235 Ok(match ty {265 Ok(match ty {