git.delta.rocks / jrsonnet / refs/commits / 71fb4e2830f5

difftreelog

perf move mergePatch to native

Yaroslav Bolyukin2024-06-18parent: #f009c16.patch.diff
in: master

4 files changed

modifiedcrates/jrsonnet-evaluator/src/stdlib/format.rsdiffbeforeafterboth
609 tmp_out.push(609 tmp_out.push(
610 std::char::from_u32(n as u32)610 std::char::from_u32(n as u32)
611 .ok_or_else(|| InvalidUnicodeCodepointGot(n as u32))?,611 .ok_or_else(|| InvalidUnicodeCodepointGot(n as u32))?,
612 )612 );
613 }613 }
614 Val::Str(s) => {614 Val::Str(s) => {
615 let s = s.into_flat();615 let s = s.into_flat();
modifiedcrates/jrsonnet-stdlib/src/lib.rsdiffbeforeafterboth
215 ("startsWith", builtin_starts_with::INST),215 ("startsWith", builtin_starts_with::INST),
216 ("endsWith", builtin_ends_with::INST),216 ("endsWith", builtin_ends_with::INST),
217 ("assertEqual", builtin_assert_equal::INST),217 ("assertEqual", builtin_assert_equal::INST),
218 ("mergePatch", builtin_merge_patch::INST),
218 // Sets219 // Sets
219 ("setMember", builtin_set_member::INST),220 ("setMember", builtin_set_member::INST),
220 ("setInter", builtin_set_inter::INST),221 ("setInter", builtin_set_inter::INST),
modifiedcrates/jrsonnet-stdlib/src/misc.rsdiffbeforeafterboth
1use std::{cell::RefCell, rc::Rc};1use std::{cell::RefCell, collections::BTreeSet, rc::Rc};
22
3use jrsonnet_evaluator::{3use jrsonnet_evaluator::{
4 bail,4 bail,
7 manifest::JsonFormat,7 manifest::JsonFormat,
8 typed::{Either2, Either4},8 typed::{Either2, Either4},
9 val::{equals, ArrValue},9 val::{equals, ArrValue},
10 Context, Either, IStr, ObjValue, ResultExt, Thunk, Val,10 Context, Either, IStr, ObjValue, ObjValueBuilder, ResultExt, Thunk, Val,
11};11};
1212
13use crate::{extvar_source, Settings};13use crate::{extvar_source, Settings};
153 bail!("assertion failed: A != B\nA: {a}\nB: {b}")153 bail!("assertion failed: A != B\nA: {a}\nB: {b}")
154}154}
155
156#[builtin]
157pub fn builtin_merge_patch(target: Val, patch: Val) -> Result<Val> {
158 let Some(patch) = patch.as_obj() else {
159 return Ok(patch);
160 };
161 let Some(target) = target.as_obj() else {
162 return Ok(Val::Obj(patch));
163 };
164 let target_fields = target.fields().into_iter().collect::<BTreeSet<IStr>>();
165 let patch_fields = patch.fields().into_iter().collect::<BTreeSet<IStr>>();
166
167 let mut out = ObjValueBuilder::new();
168 for field in target_fields.union(&patch_fields) {
169 let Some(field_patch) = patch.get(field.clone())? else {
170 out.field(field.clone()).value(target.get(field.clone())?.expect("we're iterating over fields union, if field is missing in patch - it exists in target"));
171 continue;
172 };
173 if matches!(field_patch, Val::Null) {
174 continue;
175 }
176 let Some(field_target) = target.get(field.clone())? else {
177 out.field(field.clone()).value(field_patch);
178 continue;
179 };
180 out.field(field.clone())
181 .value(builtin_merge_patch(field_target, field_patch)?);
182 }
183 Ok(out.build().into())
184}
155185
modifiedcrates/jrsonnet-stdlib/src/std.jsonnetdiffbeforeafterboth
11 else11 else
12 { [k]: func(k, obj[k]) for k in std.objectFields(obj) },12 { [k]: func(k, obj[k]) for k in std.objectFields(obj) },
1313
14 mergePatch(target, patch)::
15 if std.isObject(patch) then
16 local target_object =
17 if std.isObject(target) then target else {};
18
19 local target_fields =
20 if std.isObject(target_object) then std.objectFields(target_object) else [];
21
22 local null_fields = [k for k in std.objectFields(patch) if patch[k] == null];
23 local both_fields = std.setUnion(target_fields, std.objectFields(patch));
24
25 {
26 [k]:
27 if !std.objectHas(patch, k) then
28 target_object[k]
29 else if !std.objectHas(target_object, k) then
30 std.mergePatch(null, patch[k]) tailstrict
31 else
32 std.mergePatch(target_object[k], patch[k]) tailstrict
33 for k in std.setDiff(both_fields, null_fields)
34 }
35 else
36 patch,
37
38 resolvePath(f, r)::14 resolvePath(f, r)::
39 local arr = std.split(f, '/');15 local arr = std.split(f, '/');
40 std.join('/', std.makeArray(std.length(arr) - 1, function(i) arr[i]) + [r]),16 std.join('/', std.makeArray(std.length(arr) - 1, function(i) arr[i]) + [r]),