difftreelog
feat multi and stream manifests
in: master
5 files changed
bindings/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()
+ }
+ }
+ })
}
crates/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(
crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth95 (Val::Num(n), Val::Str(o)) => Val::Str(format!("{}{}", n, o).into()),95 (Val::Num(n), Val::Str(o)) => Val::Str(format!("{}{}", n, o).into()),96 (Val::Str(o), Val::Num(n)) => Val::Str(format!("{}{}", o, n).into()),96 (Val::Str(o), Val::Num(n)) => Val::Str(format!("{}{}", o, n).into()),979798 (Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().into_string()?).into()),98 (Val::Str(s), o) => Val::Str(format!("{}{}", s, o.clone().to_string()?).into()),99 (o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().into_string()?, s).into()),99 (o, Val::Str(s)) => Val::Str(format!("{}{}", o.clone().to_string()?, s).into()),100100101 (Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),101 (Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),102 (Val::Arr(a), Val::Arr(b)) => Val::Arr(Rc::new([&a[..], &b[..]].concat())),102 (Val::Arr(a), Val::Arr(b)) => Val::Arr(Rc::new([&a[..], &b[..]].concat())),975 if assertion_result {975 if assertion_result {976 evaluate(context, returned)?976 evaluate(context, returned)?977 } else if let Some(msg) = msg {977 } else if let Some(msg) = msg {978 throw!(AssertionFailed(evaluate(context, msg)?));978 throw!(AssertionFailed(evaluate(context, msg)?.to_string()?));979 } else {979 } else {980 throw!(AssertionFailed(Val::Null));980 throw!(AssertionFailed(Val::Null.to_string()?));981 }981 }982 }982 }983 ErrorStmt(e) => push(983 ErrorStmt(e) => push(crates/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> {
crates/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 {