git.delta.rocks / jrsonnet / refs/commits / 21712e70b26b

difftreelog

perf implement std.setDiff in native

Yaroslav Bolyukin2023-08-12parent: #0d47e9f.patch.diff
in: master

3 files changed

modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/lib.rs
+++ b/crates/jrsonnet-stdlib/src/lib.rs
@@ -175,6 +175,7 @@
 		// Sets
 		("setMember", builtin_set_member::INST),
 		("setInter", builtin_set_inter::INST),
+		("setDiff", builtin_set_diff::INST),
 		// Compat
 		("__compare", builtin___compare::INST),
 	]
modifiedcrates/jrsonnet-stdlib/src/sets.rsdiffbeforeafterboth
--- a/crates/jrsonnet-stdlib/src/sets.rs
+++ b/crates/jrsonnet-stdlib/src/sets.rs
@@ -71,3 +71,48 @@
 	}
 	Ok(ArrValue::lazy(out))
 }
+#[builtin]
+#[allow(non_snake_case, clippy::redundant_closure)]
+pub fn builtin_set_diff(a: ArrValue, b: ArrValue, keyF: Option<FuncVal>) -> Result<ArrValue> {
+	let mut a = a.iter_lazy();
+	let mut b = b.iter_lazy();
+
+	let keyF = keyF
+		.unwrap_or(FuncVal::identity())
+		.into_native::<((Thunk<Val>,), Val)>();
+	let keyF = |v| keyF(v);
+
+	let mut av = a.next();
+	let mut bv = b.next();
+	let mut ak = av.clone().map(keyF).transpose()?;
+	let mut bk = bv.map(keyF).transpose()?;
+
+	let mut out = Vec::new();
+	while let (Some(ac), Some(bc)) = (&ak, &bk) {
+		match evaluate_compare_op(ac, bc, BinaryOpType::Lt)? {
+			Ordering::Less => {
+				// In a, but not in b
+				out.push(av.clone().expect("ak != None"));
+				av = a.next();
+				ak = av.clone().map(keyF).transpose()?;
+			}
+			Ordering::Greater => {
+				bv = b.next();
+				bk = bv.map(keyF).transpose()?;
+			}
+			Ordering::Equal => {
+				av = a.next();
+				ak = av.clone().map(keyF).transpose()?;
+				bv = b.next();
+				bk = bv.map(keyF).transpose()?;
+			}
+		};
+	}
+	while let Some(ac) = &ak {
+		// In a, but not in b
+		out.push(av.clone().expect("ak != None"));
+		av = a.next();
+		ak = av.clone().map(keyF).transpose()?;
+	}
+	Ok(ArrValue::lazy(out))
+}
modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
214 aux(a, b, i, j + 1, acc + [b[j]]) tailstrict;214 aux(a, b, i, j + 1, acc + [b[j]]) tailstrict;
215 aux(a, b, 0, 0, []),215 aux(a, b, 0, 0, []),
216216
217 setDiff(a, b, keyF=id)::
218 local aux(a, b, i, j, acc) =
219 if i >= std.length(a) then
220 acc
221 else if j >= std.length(b) then
222 acc + a[i:]
223 else
224 if keyF(a[i]) == keyF(b[j]) then
225 aux(a, b, i + 1, j + 1, acc) tailstrict
226 else if keyF(a[i]) < keyF(b[j]) then
227 aux(a, b, i + 1, j, acc + [a[i]]) tailstrict
228 else
229 aux(a, b, i, j + 1, acc) tailstrict;
230 aux(a, b, 0, 0, []) tailstrict,
231
232 mergePatch(target, patch)::217 mergePatch(target, patch)::
233 if std.isObject(patch) then218 if std.isObject(patch) then
234 local target_object =219 local target_object =