git.delta.rocks / jrsonnet / refs/commits / bc97bc99f5fd

difftreelog

fix(evaluator) missing intrinsics for slice, mod

Yaroslav Bolyukin2021-01-06parent: #7c1d01a.patch.diff
in: master
Fixes #30

3 files changed

modifiedcrates/jrsonnet-evaluator/build.rsdiffbeforeafterboth
40 **name == *"escapeStringJson" || **name == *"equals" ||40 **name == *"escapeStringJson" || **name == *"equals" ||
41 **name == *"base64" || **name == *"foldl" || **name == *"foldr" ||41 **name == *"base64" || **name == *"foldl" || **name == *"foldr" ||
42 **name == *"sortImpl" || **name == *"format" || **name == *"range" || **name == *"reverse"42 **name == *"sortImpl" || **name == *"format" || **name == *"range" ||
43 **name == *"reverse" || **name == *"slice" || **name == *"mod"
43 )44 )
44 })45 })
45 .collect(),46 .collect(),
modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
16pub mod manifest;16pub mod manifest;
17pub mod sort;17pub mod sort;
1818
19#[allow(clippy::cognitive_complexity)]
20pub fn call_builtin(19fn std_format(str: Rc<str>, vals: Val) -> Result<Val> {
21 context: Context,
22 loc: &Option<ExprLocation>,
23 name: &str,
24 args: &ArgsDesc,
25) -> Result<Val> {
26 Ok(match name as &str {
27 // arr/string/function
28 "length" => parse_args!(context, "std.length", args, 1, [
29 0, x: [Val::Str|Val::Arr|Val::Obj], vec![ValType::Str, ValType::Arr, ValType::Obj];
30 ], {
31 Ok(match x {
32 Val::Str(n) => Val::Num(n.chars().count() as f64),
33 Val::Arr(i) => Val::Num(i.len() as f64),
34 Val::Obj(o) => Val::Num(
35 o.fields_visibility()
36 .into_iter()
37 .filter(|(_k, v)| *v)
38 .count() as f64,
39 ),
40 _ => unreachable!(),
41 })
42 })?,
43 // any
44 "type" => parse_args!(context, "std.type", args, 1, [
45 0, x, vec![];
46 ], {
47 Ok(Val::Str(x.value_type()?.name().into()))
48 })?,
49 // length, idx=>any
50 "makeArray" => parse_args!(context, "std.makeArray", args, 2, [
51 0, sz: [Val::Num]!!Val::Num, vec![ValType::Num];
52 1, func: [Val::Func]!!Val::Func, vec![ValType::Func];
53 ], {
54 if sz < 0.0 {
55 throw!(RuntimeError(format!("makeArray requires size >= 0, got {}", sz).into()));
56 }
57 let mut out = Vec::with_capacity(sz as usize);
58 for i in 0..sz as usize {
59 out.push(func.evaluate_values(20 push(
60 Context::new(),
61 &[Val::Num(i as f64)]
62 )?)
63 }
64 Ok(Val::Arr(Rc::new(out)))
65 })?,
66 // string
67 "codepoint" => parse_args!(context, "std.codepoint", args, 1, [
68 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
69 ], {
70 assert!(
71 str.chars().count() == 1,
72 "std.codepoint should receive single char string"
73 );
74 Ok(Val::Num(str.chars().take(1).next().unwrap() as u32 as f64))
75 })?,
76 // object, includeHidden
77 "objectFieldsEx" => parse_args!(context, "std.objectFieldsEx",args, 2, [
78 0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
79 1, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
80 ], {
81 let mut out = obj.fields_visibility()
82 .into_iter()
83 .filter(|(_k, v)| *v || inc_hidden)
84 .map(|(k, _v)|k)
85 .collect::<Vec<_>>();
86 out.sort();
87 Ok(Val::Arr(Rc::new(out.into_iter().map(Val::Str).collect())))
88 })?,
89 // object, field, includeHidden
90 "objectHasEx" => parse_args!(context, "std.objectHasEx", args, 3, [
91 0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
92 1, f: [Val::Str]!!Val::Str, vec![ValType::Str];
93 2, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
94 ], {
95 Ok(Val::Bool(
96 obj.fields_visibility()
97 .into_iter()
98 .filter(|(_k, v)| *v || inc_hidden)
99 .any(|(k, _v)| *k == *f),
100 ))
101 })?,
102 "primitiveEquals" => parse_args!(context, "std.primitiveEquals", args, 2, [
103 0, a, vec![];
104 1, b, vec![];
105 ], {
106 Ok(Val::Bool(primitive_equals(&a, &b)?))21 &Some(ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)),
107 })?,
108 // faster
109 "equals" => parse_args!(context, "std.equals", args, 2, [
110 0, a, vec![];
111 1, b, vec![];
112 ], {
113 Ok(Val::Bool(equals(&a, &b)?))
114 })?,
115 "modulo" => parse_args!(context, "std.modulo", args, 2, [
116 0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
117 1, b: [Val::Num]!!Val::Num, vec![ValType::Num];
118 ], {
119 Ok(Val::Num(a % b))
120 })?,
121 "floor" => parse_args!(context, "std.floor", args, 1, [
122 0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
123 ], {
124 Ok(Val::Num(x.floor()))
125 })?,
126 "log" => parse_args!(context, "std.log", args, 2, [
127 0, n: [Val::Num]!!Val::Num, vec![ValType::Num];
128 ], {
129 Ok(Val::Num(n.ln()))
130 })?,
131 "trace" => parse_args!(context, "std.trace", args, 2, [22 || format!("std.format of {}", str),
132 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];23 || {
133 1, rest, vec![];
134 ], {
135 eprint!("TRACE:");
136 if let Some(loc) = loc {
137 with_state(|s|{
138 let locs = s.map_source_locations(&loc.0, &[loc.1]);
139 eprint!(" {}:{}", loc.0.file_name().unwrap().to_str().unwrap(), locs[0].line);
140 });
141 }
142 eprintln!(" {}", str);
143 Ok(rest)
144 })?,
145 "pow" => parse_args!(context, "std.modulo", args, 2, [
146 0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
147 1, n: [Val::Num]!!Val::Num, vec![ValType::Num];
148 ], {
149 Ok(Val::Num(x.powf(n)))
150 })?,
151 "extVar" => parse_args!(context, "std.extVar", args, 1, [
152 0, x: [Val::Str]!!Val::Str, vec![ValType::Str];
153 ], {
154 Ok(with_state(|s| s.settings().ext_vars.get(&x).cloned()).ok_or_else(
155 || UndefinedExternalVariable(x),
156 )?)
157 })?,
158 "native" => parse_args!(context, "std.native", args, 1, [
159 0, x: [Val::Str]!!Val::Str, vec![ValType::Str];
160 ], {
161 Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Rc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or_else(
162 || UndefinedExternalFunction(x),
163 )?)
164 })?,
165 "filter" => parse_args!(context, "std.filter", args, 2, [
166 0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
167 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
168 ], {
169 Ok(Val::Arr(Rc::new(
170 arr.iter()
171 .cloned()
172 .filter(|e| {
173 func
174 .evaluate_values(context.clone(), &[e.clone()])
175 .unwrap()
176 .try_cast_bool("filter predicate")
177 .unwrap()
178 })
179 .collect(),
180 )))
181 })?,
182 // faster
183 "foldl" => parse_args!(context, "std.foldl", args, 3, [
184 0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
185 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
186 2, init, vec![];
187 ], {
188 let mut acc = init;
189 for i in arr.iter().cloned() {
190 acc = func.evaluate_values(context.clone(), &[acc, i])?;
191 }
192 Ok(acc)
193 })?,
194 // faster
195 "foldr" => parse_args!(context, "std.foldr", args, 3, [
196 0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
197 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
198 2, init, vec![];
199 ], {
200 let mut acc = init;
201 for i in arr.iter().rev().cloned() {
202 acc = func.evaluate_values(context.clone(), &[acc, i])?;
203 }
204 Ok(acc)
205 })?,
206 // faster
207 #[allow(non_snake_case)]
208 "sortImpl" => parse_args!(context, "std.sort", args, 2, [
209 0, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
210 1, keyF: [Val::Func]!!Val::Func, vec![ValType::Func];
211 ], {
212 if arr.len() <= 1 {
213 return Ok(Val::Arr(arr))
214 }
215 Ok(Val::Arr(sort::sort(context, arr, &keyF)?))
216 })?,
217 // faster
218 "format" => parse_args!(context, "std.format", args, 2, [
219 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
220 1, vals, vec![]
221 ], {
222 push(&Some(ExprLocation(Rc::from(PathBuf::from("std.jsonnet")), 0, 0)), ||format!("std.format of {}", str), ||{
223 Ok(match vals {24 Ok(match vals {
224 Val::Arr(vals) => Val::Str(format_arr(&str, &vals)?.into()),25 Val::Arr(vals) => Val::Str(format_arr(&str, &vals)?.into()),
225 Val::Obj(obj) => Val::Str(format_obj(&str, &obj)?.into()),26 Val::Obj(obj) => Val::Str(format_obj(&str, &obj)?.into()),
226 o => Val::Str(format_arr(&str, &[o])?.into()),27 o => Val::Str(format_arr(&str, &[o])?.into()),
227 })28 })
228 })29 },
229 })?,30 )
230 // faster
231 "range" => parse_args!(context, "std.range", args, 2, [
232 0, from: [Val::Num]!!Val::Num, vec![ValType::Num];
233 1, to: [Val::Num]!!Val::Num, vec![ValType::Num];
234 ], {
235 let mut out = Vec::with_capacity((1+to as usize-from as usize).max(0));
236 for i in from as usize..=to as usize {
237 out.push(Val::Num(i as f64));
238 }
239 Ok(Val::Arr(Rc::new(out)))
240 })?,
241 "char" => parse_args!(context, "std.char", args, 1, [
242 0, n: [Val::Num]!!Val::Num, vec![ValType::Num];
243 ], {
244 let mut out = String::new();
245 out.push(std::char::from_u32(n as u32).ok_or_else(||
246 InvalidUnicodeCodepointGot(n as u32)
247 )?);
248 Ok(Val::Str(out.into()))
249 })?,
250 "encodeUTF8" => parse_args!(context, "std.encodeUtf8", args, 1, [
251 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
252 ], {
253 Ok(Val::Arr(Rc::new(str.bytes().map(|b| Val::Num(b as f64)).collect())))
254 })?,
255 "md5" => parse_args!(context, "std.md5", args, 1, [
256 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
257 ], {
258 Ok(Val::Str(format!("{:x}", md5::compute(&str.as_bytes())).into()))
259 })?,
260 // faster
261 "base64" => parse_args!(context, "std.base64", args, 1, [
262 0, input: [Val::Str | Val::Arr], vec![ValType::Arr, ValType::Str];
263 ], {
264 Ok(Val::Str(match input {
265 Val::Str(s) => {
266 base64::encode(s.bytes().collect::<Vec<_>>()).into()
267 },
268 Val::Arr(a) => {
269 base64::encode(a.iter().map(|v| {
270 Ok(v.clone().try_cast_num("base64 array")? as u8)
271 }).collect::<Result<Vec<_>>>()?).into()
272 },
273 _ => unreachable!()
274 }))
275 })?,
276 // faster
277 "join" => parse_args!(context, "std.join", args, 2, [
278 0, sep: [Val::Str|Val::Arr], vec![ValType::Str, ValType::Arr];
279 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
280 ], {
281 Ok(match sep {
282 Val::Arr(joiner_items) => {
283 let mut out = Vec::new();
284
285 let mut first = true;
286 for item in arr.iter().cloned() {
287 if let Val::Arr(items) = item.unwrap_if_lazy()? {
288 if !first {
289 out.reserve(joiner_items.len());
290 out.extend(joiner_items.iter().cloned());
291 }
292 first = false;
293 out.reserve(items.len());
294 out.extend(items.iter().cloned());
295 } else {
296 throw!(RuntimeError("in std.join all items should be arrays".into()));
297 }
298 }
299
300 Val::Arr(Rc::new(out))
301 },
302 Val::Str(sep) => {
303 let mut out = String::new();
304
305 let mut first = true;
306 for item in arr.iter().cloned() {
307 if let Val::Str(item) = item.unwrap_if_lazy()? {
308 if !first {
309 out += &sep;
310 }
311 first = false;
312 out += &item;
313 } else {
314 throw!(RuntimeError("in std.join all items should be strings".into()));
315 }
316 }
317
318 Val::Str(out.into())
319 },
320 _ => unreachable!()
321 })
322 })?,
323 // Faster
324 "escapeStringJson" => parse_args!(context, "std.escapeStringJson", args, 1, [
325 0, str_: [Val::Str]!!Val::Str, vec![ValType::Str];
326 ], {
327 Ok(Val::Str(escape_string_json(&str_).into()))
328 })?,
329 // Faster
330 "manifestJsonEx" => parse_args!(context, "std.manifestJsonEx", args, 2, [
331 0, value, vec![];
332 1, indent: [Val::Str]!!Val::Str, vec![ValType::Str];
333 ], {
334 Ok(Val::Str(manifest_json_ex(&value, &ManifestJsonOptions {
335 padding: &indent,
336 mtype: ManifestType::Std,
337 })?.into()))
338 })?,
339 // Faster
340 "reverse" => parse_args!(context, "std.reverse", args, 1, [
341 0, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
342 ], {
343 let mut marr = arr;
344 Rc::make_mut(&mut marr).reverse();
345 Ok(Val::Arr(marr))
346 })?,
347 "id" => parse_args!(context, "std.id", args, 1, [
348 0, v, vec![];
349 ], {
350 Ok(v)
351 })?,
352 name => throw!(IntrinsicNotFound(name.into())),
353 })
354}31}
32
33#[allow(clippy::cognitive_complexity)]
34pub fn call_builtin(
35 context: Context,
36 loc: &Option<ExprLocation>,
37 name: &str,
38 args: &ArgsDesc,
39) -> Result<Val> {
40 Ok(match name as &str {
41 // arr/string/function
42 "length" => parse_args!(context, "std.length", args, 1, [
43 0, x: [Val::Str|Val::Arr|Val::Obj], vec![ValType::Str, ValType::Arr, ValType::Obj];
44 ], {
45 Ok(match x {
46 Val::Str(n) => Val::Num(n.chars().count() as f64),
47 Val::Arr(i) => Val::Num(i.len() as f64),
48 Val::Obj(o) => Val::Num(
49 o.fields_visibility()
50 .into_iter()
51 .filter(|(_k, v)| *v)
52 .count() as f64,
53 ),
54 _ => unreachable!(),
55 })
56 })?,
57 // any
58 "type" => parse_args!(context, "std.type", args, 1, [
59 0, x, vec![];
60 ], {
61 Ok(Val::Str(x.value_type()?.name().into()))
62 })?,
63 // length, idx=>any
64 "makeArray" => parse_args!(context, "std.makeArray", args, 2, [
65 0, sz: [Val::Num]!!Val::Num, vec![ValType::Num];
66 1, func: [Val::Func]!!Val::Func, vec![ValType::Func];
67 ], {
68 if sz < 0.0 {
69 throw!(RuntimeError(format!("makeArray requires size >= 0, got {}", sz).into()));
70 }
71 let mut out = Vec::with_capacity(sz as usize);
72 for i in 0..sz as usize {
73 out.push(func.evaluate_values(
74 Context::new(),
75 &[Val::Num(i as f64)]
76 )?)
77 }
78 Ok(Val::Arr(Rc::new(out)))
79 })?,
80 // string
81 "codepoint" => parse_args!(context, "std.codepoint", args, 1, [
82 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
83 ], {
84 assert!(
85 str.chars().count() == 1,
86 "std.codepoint should receive single char string"
87 );
88 Ok(Val::Num(str.chars().take(1).next().unwrap() as u32 as f64))
89 })?,
90 // object, includeHidden
91 "objectFieldsEx" => parse_args!(context, "std.objectFieldsEx",args, 2, [
92 0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
93 1, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
94 ], {
95 let mut out = obj.fields_visibility()
96 .into_iter()
97 .filter(|(_k, v)| *v || inc_hidden)
98 .map(|(k, _v)|k)
99 .collect::<Vec<_>>();
100 out.sort();
101 Ok(Val::Arr(Rc::new(out.into_iter().map(Val::Str).collect())))
102 })?,
103 // object, field, includeHidden
104 "objectHasEx" => parse_args!(context, "std.objectHasEx", args, 3, [
105 0, obj: [Val::Obj]!!Val::Obj, vec![ValType::Obj];
106 1, f: [Val::Str]!!Val::Str, vec![ValType::Str];
107 2, inc_hidden: [Val::Bool]!!Val::Bool, vec![ValType::Bool];
108 ], {
109 Ok(Val::Bool(
110 obj.fields_visibility()
111 .into_iter()
112 .filter(|(_k, v)| *v || inc_hidden)
113 .any(|(k, _v)| *k == *f),
114 ))
115 })?,
116
117 // faster
118 "slice" => parse_args!(context, "slice", args, 4, [
119 0, indexable: [Val::Str | Val::Arr], vec![ValType::Str, ValType::Arr];
120 1, index, vec![ValType::Num, ValType::Null];
121 2, end, vec![ValType::Num, ValType::Null];
122 3, step, vec![ValType::Num, ValType::Null];
123 ], {
124 let index = match index {
125 Val::Num(v) => v as usize,
126 Val::Null => 0,
127 _ => unreachable!(),
128 };
129 let end = match end {
130 Val::Num(v) => v as usize,
131 Val::Null => match &indexable {
132 Val::Str(s) => s.chars().count(),
133 Val::Arr(v) => v.len(),
134 _ => unreachable!()
135 },
136 _ => unreachable!()
137 };
138 let step = match step {
139 Val::Num(v) => v as usize,
140 Val::Null => 1,
141 _ => unreachable!()
142 };
143 match &indexable {
144 Val::Str(s) => {
145 Ok(Val::Str((s.chars().skip(index).take(end-index).step_by(step).collect::<String>()).into()))
146 }
147 Val::Arr(arr) => {
148 Ok(Val::Arr((arr.iter().skip(index).take(end-index).step_by(step).cloned().collect::<Vec<Val>>()).into()))
149 }
150 _ => unreachable!()
151 }
152 })?,
153 "primitiveEquals" => parse_args!(context, "std.primitiveEquals", args, 2, [
154 0, a, vec![];
155 1, b, vec![];
156 ], {
157 Ok(Val::Bool(primitive_equals(&a, &b)?))
158 })?,
159 // faster
160 "equals" => parse_args!(context, "std.equals", args, 2, [
161 0, a, vec![];
162 1, b, vec![];
163 ], {
164 Ok(Val::Bool(equals(&a, &b)?))
165 })?,
166 "mod" => parse_args!(context, "std.mod", args, 2, [
167 0, a: [Val::Num | Val::Str], vec![ValType::Num, ValType::Str];
168 1, b, vec![];
169 ], {
170 match (a, b) {
171 (Val::Num(a), Val::Num(b)) => Ok(Val::Num(a % b)),
172 (Val::Str(str), vals) => std_format(str, vals),
173 (a, b) => throw!(BinaryOperatorDoesNotOperateOnValues(jrsonnet_parser::BinaryOpType::Mod, a.value_type()?, b.value_type()?))
174 }
175 })?,
176 "modulo" => parse_args!(context, "std.modulo", args, 2, [
177 0, a: [Val::Num]!!Val::Num, vec![ValType::Num];
178 1, b: [Val::Num]!!Val::Num, vec![ValType::Num];
179 ], {
180 Ok(Val::Num(a % b))
181 })?,
182 "floor" => parse_args!(context, "std.floor", args, 1, [
183 0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
184 ], {
185 Ok(Val::Num(x.floor()))
186 })?,
187 "log" => parse_args!(context, "std.log", args, 2, [
188 0, n: [Val::Num]!!Val::Num, vec![ValType::Num];
189 ], {
190 Ok(Val::Num(n.ln()))
191 })?,
192 "trace" => parse_args!(context, "std.trace", args, 2, [
193 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
194 1, rest, vec![];
195 ], {
196 eprint!("TRACE:");
197 if let Some(loc) = loc {
198 with_state(|s|{
199 let locs = s.map_source_locations(&loc.0, &[loc.1]);
200 eprint!(" {}:{}", loc.0.file_name().unwrap().to_str().unwrap(), locs[0].line);
201 });
202 }
203 eprintln!(" {}", str);
204 Ok(rest)
205 })?,
206 "pow" => parse_args!(context, "std.modulo", args, 2, [
207 0, x: [Val::Num]!!Val::Num, vec![ValType::Num];
208 1, n: [Val::Num]!!Val::Num, vec![ValType::Num];
209 ], {
210 Ok(Val::Num(x.powf(n)))
211 })?,
212 "extVar" => parse_args!(context, "std.extVar", args, 1, [
213 0, x: [Val::Str]!!Val::Str, vec![ValType::Str];
214 ], {
215 Ok(with_state(|s| s.settings().ext_vars.get(&x).cloned()).ok_or_else(
216 || UndefinedExternalVariable(x),
217 )?)
218 })?,
219 "native" => parse_args!(context, "std.native", args, 1, [
220 0, x: [Val::Str]!!Val::Str, vec![ValType::Str];
221 ], {
222 Ok(with_state(|s| s.settings().ext_natives.get(&x).cloned()).map(|v| Val::Func(Rc::new(FuncVal::NativeExt(x.clone(), v)))).ok_or_else(
223 || UndefinedExternalFunction(x),
224 )?)
225 })?,
226 "filter" => parse_args!(context, "std.filter", args, 2, [
227 0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
228 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
229 ], {
230 Ok(Val::Arr(Rc::new(
231 arr.iter()
232 .cloned()
233 .filter(|e| {
234 func
235 .evaluate_values(context.clone(), &[e.clone()])
236 .unwrap()
237 .try_cast_bool("filter predicate")
238 .unwrap()
239 })
240 .collect(),
241 )))
242 })?,
243 // faster
244 "foldl" => parse_args!(context, "std.foldl", args, 3, [
245 0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
246 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
247 2, init, vec![];
248 ], {
249 let mut acc = init;
250 for i in arr.iter().cloned() {
251 acc = func.evaluate_values(context.clone(), &[acc, i])?;
252 }
253 Ok(acc)
254 })?,
255 // faster
256 "foldr" => parse_args!(context, "std.foldr", args, 3, [
257 0, func: [Val::Func]!!Val::Func, vec![ValType::Func];
258 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
259 2, init, vec![];
260 ], {
261 let mut acc = init;
262 for i in arr.iter().rev().cloned() {
263 acc = func.evaluate_values(context.clone(), &[acc, i])?;
264 }
265 Ok(acc)
266 })?,
267 // faster
268 #[allow(non_snake_case)]
269 "sortImpl" => parse_args!(context, "std.sort", args, 2, [
270 0, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
271 1, keyF: [Val::Func]!!Val::Func, vec![ValType::Func];
272 ], {
273 if arr.len() <= 1 {
274 return Ok(Val::Arr(arr))
275 }
276 Ok(Val::Arr(sort::sort(context, arr, &keyF)?))
277 })?,
278 // faster
279 "format" => parse_args!(context, "std.format", args, 2, [
280 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
281 1, vals, vec![]
282 ], {
283 std_format(str, vals)
284 })?,
285 // faster
286 "range" => parse_args!(context, "std.range", args, 2, [
287 0, from: [Val::Num]!!Val::Num, vec![ValType::Num];
288 1, to: [Val::Num]!!Val::Num, vec![ValType::Num];
289 ], {
290 let mut out = Vec::with_capacity((1+to as usize-from as usize).max(0));
291 for i in from as usize..=to as usize {
292 out.push(Val::Num(i as f64));
293 }
294 Ok(Val::Arr(Rc::new(out)))
295 })?,
296 "char" => parse_args!(context, "std.char", args, 1, [
297 0, n: [Val::Num]!!Val::Num, vec![ValType::Num];
298 ], {
299 let mut out = String::new();
300 out.push(std::char::from_u32(n as u32).ok_or_else(||
301 InvalidUnicodeCodepointGot(n as u32)
302 )?);
303 Ok(Val::Str(out.into()))
304 })?,
305 "encodeUTF8" => parse_args!(context, "std.encodeUtf8", args, 1, [
306 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
307 ], {
308 Ok(Val::Arr(Rc::new(str.bytes().map(|b| Val::Num(b as f64)).collect())))
309 })?,
310 "md5" => parse_args!(context, "std.md5", args, 1, [
311 0, str: [Val::Str]!!Val::Str, vec![ValType::Str];
312 ], {
313 Ok(Val::Str(format!("{:x}", md5::compute(&str.as_bytes())).into()))
314 })?,
315 // faster
316 "base64" => parse_args!(context, "std.base64", args, 1, [
317 0, input: [Val::Str | Val::Arr], vec![ValType::Arr, ValType::Str];
318 ], {
319 Ok(Val::Str(match input {
320 Val::Str(s) => {
321 base64::encode(s.bytes().collect::<Vec<_>>()).into()
322 },
323 Val::Arr(a) => {
324 base64::encode(a.iter().map(|v| {
325 Ok(v.clone().try_cast_num("base64 array")? as u8)
326 }).collect::<Result<Vec<_>>>()?).into()
327 },
328 _ => unreachable!()
329 }))
330 })?,
331 // faster
332 "join" => parse_args!(context, "std.join", args, 2, [
333 0, sep: [Val::Str|Val::Arr], vec![ValType::Str, ValType::Arr];
334 1, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
335 ], {
336 Ok(match sep {
337 Val::Arr(joiner_items) => {
338 let mut out = Vec::new();
339
340 let mut first = true;
341 for item in arr.iter().cloned() {
342 if let Val::Arr(items) = item.unwrap_if_lazy()? {
343 if !first {
344 out.reserve(joiner_items.len());
345 out.extend(joiner_items.iter().cloned());
346 }
347 first = false;
348 out.reserve(items.len());
349 out.extend(items.iter().cloned());
350 } else {
351 throw!(RuntimeError("in std.join all items should be arrays".into()));
352 }
353 }
354
355 Val::Arr(Rc::new(out))
356 },
357 Val::Str(sep) => {
358 let mut out = String::new();
359
360 let mut first = true;
361 for item in arr.iter().cloned() {
362 if let Val::Str(item) = item.unwrap_if_lazy()? {
363 if !first {
364 out += &sep;
365 }
366 first = false;
367 out += &item;
368 } else {
369 throw!(RuntimeError("in std.join all items should be strings".into()));
370 }
371 }
372
373 Val::Str(out.into())
374 },
375 _ => unreachable!()
376 })
377 })?,
378 // Faster
379 "escapeStringJson" => parse_args!(context, "std.escapeStringJson", args, 1, [
380 0, str_: [Val::Str]!!Val::Str, vec![ValType::Str];
381 ], {
382 Ok(Val::Str(escape_string_json(&str_).into()))
383 })?,
384 // Faster
385 "manifestJsonEx" => parse_args!(context, "std.manifestJsonEx", args, 2, [
386 0, value, vec![];
387 1, indent: [Val::Str]!!Val::Str, vec![ValType::Str];
388 ], {
389 Ok(Val::Str(manifest_json_ex(&value, &ManifestJsonOptions {
390 padding: &indent,
391 mtype: ManifestType::Std,
392 })?.into()))
393 })?,
394 // Faster
395 "reverse" => parse_args!(context, "std.reverse", args, 1, [
396 0, arr: [Val::Arr]!!Val::Arr, vec![ValType::Arr];
397 ], {
398 let mut marr = arr;
399 Rc::make_mut(&mut marr).reverse();
400 Ok(Val::Arr(marr))
401 })?,
402 "id" => parse_args!(context, "std.id", args, 1, [
403 0, v, vec![];
404 ], {
405 Ok(v)
406 })?,
407 name => throw!(IntrinsicNotFound(name.into())),
408 })
409}
355410
modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
97 Mul,97 Mul,
98 Div,98 Div,
99
100 Mod,
99101
100 Add,102 Add,
101 Sub,103 Sub,
124 match self {126 match self {
125 Mul => "*",127 Mul => "*",
126 Div => "/",128 Div => "/",
129 Mod => "%",
127 Add => "+",130 Add => "+",
128 Sub => "-",131 Sub => "-",
129 Lhs => "<<",132 Lhs => "<<",