1use crate::error::{JsonnetError, Result};
4use crate::value::JsonnetValue;
5use sha1::Sha1;
6use sha2::{Sha256, Sha512, Digest};
7use sha3::Sha3_256;
8use std::collections::HashMap;
9
10pub struct StdLib;
12
13impl StdLib {
14 pub fn call_function(name: &str, args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
16 match name {
17 "length" => Self::length(args),
18 "type" => Self::type_of(args),
19 "makeArray" => Self::make_array(args),
20 "filter" => Self::filter(args),
21 "map" => Self::map(args),
22 "foldl" => Self::foldl(args),
23 "foldr" => Self::foldr(args),
24 "range" => Self::range(args),
25 "join" => Self::join(args),
26 "split" => Self::split(args),
27 "contains" => Self::contains(args),
28 "startsWith" => Self::starts_with(args),
29 "endsWith" => Self::ends_with(args),
30 "toLower" => Self::to_lower(args),
31 "toUpper" => Self::to_upper(args),
32 "trim" => Self::trim(args),
33 "substr" => Self::substr(args),
34 "char" => Self::char_fn(args),
35 "codepoint" => Self::codepoint(args),
36 "toString" => Self::to_string(args),
37 "parseInt" => Self::parse_int(args),
38 "parseJson" => Self::parse_json(args),
39 "encodeUTF8" => Self::encode_utf8(args),
40 "decodeUTF8" => Self::decode_utf8(args),
41 "md5" => Self::md5(args),
42 "base64" => Self::base64(args),
43 "base64Decode" => Self::base64_decode(args),
44 "manifestJson" => Self::manifest_json(args),
45 "manifestJsonEx" => Self::manifest_json_ex(args),
46 "manifestYaml" => Self::manifest_yaml(args),
47 "escapeStringJson" => Self::escape_string_json(args),
48 "escapeStringYaml" => Self::escape_string_yaml(args),
49 "escapeStringPython" => Self::escape_string_python(args),
50 "escapeStringBash" => Self::escape_string_bash(args),
51 "escapeStringDollars" => Self::escape_string_dollars(args),
52 "stringChars" => Self::string_chars(args),
53 "stringBytes" => Self::string_bytes(args),
54 "format" => Self::format(args),
55 "isArray" => Self::is_array(args),
56 "isBoolean" => Self::is_boolean(args),
57 "isFunction" => Self::is_function(args),
58 "isNumber" => Self::is_number(args),
59 "isObject" => Self::is_object(args),
60 "isString" => Self::is_string(args),
61 "count" => Self::count(args),
62 "find" => Self::find(args),
63 "member" => Self::member(args),
64 "modulo" => Self::modulo(args),
65 "pow" => Self::pow(args),
66 "exp" => Self::exp(args),
67 "log" => Self::log(args),
68 "sqrt" => Self::sqrt(args),
69 "sin" => Self::sin(args),
70 "cos" => Self::cos(args),
71 "tan" => Self::tan(args),
72 "asin" => Self::asin(args),
73 "acos" => Self::acos(args),
74 "atan" => Self::atan(args),
75 "floor" => Self::floor(args),
76 "ceil" => Self::ceil(args),
77 "round" => Self::round(args),
78 "abs" => Self::abs(args),
79 "max" => Self::max(args),
80 "min" => Self::min(args),
81 "clamp" => Self::clamp(args),
82 "assertEqual" => Self::assert_equal(args),
83 "trace" => Self::trace(args),
84 "sort" => Self::sort(args),
85 "uniq" => Self::uniq(args),
86 "reverse" => Self::reverse(args),
87 "all" => Self::all(args),
88 "any" => Self::any(args),
89 "mergePatch" => Self::merge_patch(args),
90 "get" => Self::get(args),
91 "id" => Self::id(args),
92 "equals" => Self::equals(args),
93 "lines" => Self::lines(args),
94 "strReplace" => Self::str_replace(args),
95 "sha1" => Self::sha1(args),
96 "sha256" => Self::sha256(args),
97 "sha3" => Self::sha3(args),
98 "sha512" => Self::sha512(args),
99 "asciiLower" => Self::ascii_lower(args),
100 "asciiUpper" => Self::ascii_upper(args),
101 "set" => Self::set(args),
102 "flatMap" => Self::flat_map(args),
103 "mapWithIndex" => Self::map_with_index(args),
104 "lstripChars" => Self::lstrip_chars(args),
105 "rstripChars" => Self::rstrip_chars(args),
106 "stripChars" => Self::strip_chars(args),
107 "findSubstr" => Self::find_substr(args),
108 "repeat" => Self::repeat(args),
109 "setMember" => Self::set_member(args),
110 "setUnion" => Self::set_union(args),
111 "setInter" => Self::set_inter(args),
112 "setDiff" => Self::set_diff(args),
113 "objectFields" => Self::object_fields(args),
114 "objectFieldsAll" => Self::object_fields_all(args),
115 "objectHas" => Self::object_has(args),
116 "objectHasAll" => Self::object_has_all(args),
117 "objectValues" => Self::object_values(args),
118 "objectValuesAll" => Self::object_values_all(args),
119 "objectFieldsEx" => Self::object_fields_ex(args),
120 "objectValuesEx" => Self::object_values_ex(args),
121 "prune" => Self::prune(args),
122 "mapWithKey" => Self::map_with_key(args),
123 "manifestIni" => Self::manifest_ini(args),
124 "manifestPython" => Self::manifest_python(args),
125 "manifestCpp" => Self::manifest_cpp(args),
126 "manifestXmlJsonml" => Self::manifest_xml_jsonml(args),
127 "log2" => Self::log2(args),
128 "log10" => Self::log10(args),
129 "log1p" => Self::log1p(args),
130 "expm1" => Self::expm1(args),
131 "remove" => Self::remove(args),
132 "removeAt" => Self::remove_at(args),
133 "flattenArrays" => Self::flatten_arrays(args),
134 "objectKeysValues" => Self::object_keys_values(args),
135 "objectRemoveKey" => Self::object_remove_key(args),
136 "isInteger" => Self::is_integer(args),
137 "isDecimal" => Self::is_decimal(args),
138 "isEven" => Self::is_even(args),
139 "isOdd" => Self::is_odd(args),
140 _ => Err(JsonnetError::runtime_error(format!("Unknown std function: {}", name))),
141 }
142 }
143
144 pub fn length(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
146 Self::check_args(&args, 1, "length")?;
147 match &args[0] {
148 JsonnetValue::Array(arr) => Ok(JsonnetValue::number(arr.len() as f64)),
149 JsonnetValue::String(s) => Ok(JsonnetValue::number(s.len() as f64)),
150 JsonnetValue::Object(obj) => Ok(JsonnetValue::number(obj.len() as f64)),
151 _ => Err(JsonnetError::type_error("length() requires array, string, or object")),
152 }
153 }
154
155 fn type_of(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
157 Self::check_args(&args, 1, "type")?;
158 let type_str = args[0].type_name();
159 Ok(JsonnetValue::string(type_str))
160 }
161
162 fn make_array(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
164 Self::check_args(&args, 2, "makeArray")?;
165 let n = args[0].as_number()? as usize;
166 let _func = &args[1];
167
168 let mut result = Vec::new();
171 for i in 0..n {
172 result.push(JsonnetValue::number(i as f64));
174 }
175
176 Ok(JsonnetValue::array(result))
177 }
178
179 fn filter(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
181 Self::check_args(&args, 2, "filter")?;
182 let _func = &args[0];
183 let _arr = args[1].as_array()?;
184 Ok(args[1].clone())
187 }
188
189 fn map(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
191 Self::check_args(&args, 2, "map")?;
192 let _func = &args[0];
193 let _arr = args[1].as_array()?;
194 Ok(args[1].clone())
197 }
198
199 fn foldl(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
201 Self::check_args(&args, 3, "foldl")?;
202 let _func = &args[0];
203 let _arr = args[1].as_array()?;
204 Ok(args[2].clone())
207 }
208
209 fn foldr(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
211 Self::check_args(&args, 3, "foldr")?;
212 let _func = &args[0];
213 let _arr = args[1].as_array()?;
214 Ok(args[2].clone())
217 }
218
219 fn range(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
221 Self::check_args(&args, 1, "range")?;
222 let n = args[0].as_number()? as usize;
223 let arr: Vec<JsonnetValue> = (0..n).map(|i| JsonnetValue::number(i as f64)).collect();
224 Ok(JsonnetValue::array(arr))
225 }
226
227 fn join(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
229 Self::check_args(&args, 2, "join")?;
230 let sep = args[0].as_string()?;
231 let arr = args[1].as_array()?;
232
233 let mut result = String::new();
234 for (i, item) in arr.iter().enumerate() {
235 if i > 0 {
236 result.push_str(sep);
237 }
238 result.push_str(&item.to_string());
239 }
240
241 Ok(JsonnetValue::string(result))
242 }
243
244 fn split(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
246 Self::check_args(&args, 2, "split")?;
247 let s = args[0].as_string()?;
248 let sep = args[1].as_string()?;
249
250 let parts: Vec<JsonnetValue> = s.split(sep).map(JsonnetValue::string).collect();
251 Ok(JsonnetValue::array(parts))
252 }
253
254 fn contains(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
256 Self::check_args(&args, 2, "contains")?;
257 let arr = args[0].as_array()?;
258 let contains = arr.iter().any(|item| item.equals(&args[1]));
259 Ok(JsonnetValue::boolean(contains))
260 }
261
262 fn starts_with(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
264 Self::check_args(&args, 2, "startsWith")?;
265 let s = args[0].as_string()?;
266 let prefix = args[1].as_string()?;
267 Ok(JsonnetValue::boolean(s.starts_with(prefix)))
268 }
269
270 fn ends_with(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
272 Self::check_args(&args, 2, "endsWith")?;
273 let s = args[0].as_string()?;
274 let suffix = args[1].as_string()?;
275 Ok(JsonnetValue::boolean(s.ends_with(suffix)))
276 }
277
278 fn substr(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
280 Self::check_args(&args, 3, "substr")?;
281 let s = args[0].as_string()?;
282 let from = args[1].as_number()? as usize;
283 let len = args[2].as_number()? as usize;
284
285 let substr = if from >= s.len() {
286 ""
287 } else {
288 let end = (from + len).min(s.len());
289 &s[from..end]
290 };
291
292 Ok(JsonnetValue::string(substr))
293 }
294
295 fn char_fn(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
297 Self::check_args(&args, 1, "char")?;
298 let n = args[0].as_number()? as u32;
299 match char::from_u32(n) {
300 Some(c) => Ok(JsonnetValue::string(c.to_string())),
301 None => Err(JsonnetError::runtime_error("Invalid codepoint")),
302 }
303 }
304
305 fn codepoint(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
307 Self::check_args(&args, 1, "codepoint")?;
308 let s = args[0].as_string()?;
309 match s.chars().next() {
310 Some(c) => Ok(JsonnetValue::number(c as u32 as f64)),
311 None => Err(JsonnetError::runtime_error("Empty string")),
312 }
313 }
314
315 fn to_string(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
317 Self::check_args(&args, 1, "toString")?;
318 Ok(JsonnetValue::string(args[0].to_string()))
319 }
320
321 fn parse_int(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
323 Self::check_args(&args, 1, "parseInt")?;
324 let s = args[0].as_string()?;
325 match s.parse::<f64>() {
326 Ok(n) => Ok(JsonnetValue::number(n)),
327 Err(_) => Err(JsonnetError::runtime_error("Invalid number format")),
328 }
329 }
330
331 fn parse_json(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
333 Self::check_args(&args, 1, "parseJson")?;
334 let s = args[0].as_string()?;
335 match serde_json::from_str::<serde_json::Value>(s) {
336 Ok(value) => Ok(JsonnetValue::from_json_value(value)),
337 Err(_) => Err(JsonnetError::runtime_error("Invalid JSON")),
338 }
339 }
340
341 fn encode_utf8(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
343 Self::check_args(&args, 1, "encodeUTF8")?;
344 let s = args[0].as_string()?;
345 let bytes: Vec<JsonnetValue> = s.as_bytes().iter().map(|&b| JsonnetValue::number(b as f64)).collect();
346 Ok(JsonnetValue::array(bytes))
347 }
348
349 fn decode_utf8(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
351 Self::check_args(&args, 1, "decodeUTF8")?;
352 let arr = args[0].as_array()?;
353 let mut bytes = Vec::new();
354 for item in arr {
355 let b = item.as_number()? as u8;
356 bytes.push(b);
357 }
358 match String::from_utf8(bytes) {
359 Ok(s) => Ok(JsonnetValue::string(s)),
360 Err(_) => Err(JsonnetError::runtime_error("Invalid UTF-8 sequence")),
361 }
362 }
363
364 fn md5(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
366 Self::check_args(&args, 1, "md5")?;
367 let s = args[0].as_string()?;
368 use md5::{Md5, Digest};
369 let mut hasher = Md5::new();
370 hasher.update(s.as_bytes());
371 let result = hasher.finalize();
372 Ok(JsonnetValue::string(format!("{:x}", result)))
373 }
374
375 fn base64(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
377 Self::check_args(&args, 1, "base64")?;
378 let s = args[0].as_string()?;
379 use base64::{Engine as _, engine::general_purpose};
380 let encoded = general_purpose::STANDARD.encode(s.as_bytes());
381 Ok(JsonnetValue::string(encoded))
382 }
383
384 fn base64_decode(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
386 Self::check_args(&args, 1, "base64Decode")?;
387 let s = args[0].as_string()?;
388 use base64::{Engine as _, engine::general_purpose};
389 match general_purpose::STANDARD.decode(s.as_bytes()) {
390 Ok(bytes) => match String::from_utf8(bytes) {
391 Ok(decoded) => Ok(JsonnetValue::string(decoded)),
392 Err(_) => Err(JsonnetError::runtime_error("Invalid UTF-8 in decoded data")),
393 },
394 Err(_) => Err(JsonnetError::runtime_error("Invalid base64")),
395 }
396 }
397
398 fn manifest_json(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
400 Self::check_args(&args, 1, "manifestJson")?;
401 let json = serde_json::to_string_pretty(&args[0].to_json_value())?;
402 Ok(JsonnetValue::string(json))
403 }
404
405 fn manifest_json_ex(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
407 Self::check_args(&args, 2, "manifestJsonEx")?;
408 let value = &args[0];
409 let indent = args[1].as_string()?;
410
411 match serde_json::to_string_pretty(&value.to_json_value()) {
414 Ok(json) => {
415 if indent.is_empty() {
416 Ok(JsonnetValue::string(json))
417 } else {
418 let indented = json.lines()
420 .map(|line| {
421 let leading_spaces = line.chars().take_while(|c| *c == ' ').count();
422 if leading_spaces > 0 {
423 let indent_level = leading_spaces / 2;
424 format!("{}{}", indent.repeat(indent_level), &line[leading_spaces..])
425 } else {
426 line.to_string()
427 }
428 })
429 .collect::<Vec<_>>()
430 .join("\n");
431 Ok(JsonnetValue::string(indented))
432 }
433 }
434 Err(_) => Err(JsonnetError::runtime_error("Failed to serialize to JSON")),
435 }
436 }
437
438 #[cfg(feature = "yaml")]
440 fn manifest_yaml(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
441 Self::check_args(&args, 1, "manifestYaml")?;
442 let yaml = serde_yaml::to_string(&args[0].to_json_value())?;
443 Ok(JsonnetValue::string(yaml))
444 }
445
446 #[cfg(not(feature = "yaml"))]
448 fn manifest_yaml(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
449 Self::check_args(&args, 1, "manifestYaml")?;
450 Self::manifest_json(args)
452 }
453
454 fn escape_string_json(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
456 Self::check_args(&args, 1, "escapeStringJson")?;
457 let s = args[0].as_string()?;
458 let escaped = serde_json::to_string(s)?;
459 Ok(JsonnetValue::string(escaped))
460 }
461
462 fn escape_string_yaml(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
463 Self::check_args(&args, 1, "escapeStringYaml")?;
464 let s = args[0].as_string()?;
465
466 let mut escaped = String::new();
469 for ch in s.chars() {
470 match ch {
471 '"' => escaped.push_str("\\\""),
472 '\\' => escaped.push_str("\\\\"),
473 '\n' => escaped.push_str("\\n"),
474 '\r' => escaped.push_str("\\r"),
475 '\t' => escaped.push_str("\\t"),
476 '\0' => escaped.push_str("\\0"),
477 _ => escaped.push(ch),
478 }
479 }
480
481 let needs_quotes = s.contains(' ') || s.contains('\t') || s.contains('\n') ||
483 s.contains(':') || s.contains('#') || s.contains('-') ||
484 s.starts_with('[') || s.starts_with('{') ||
485 s.starts_with('"') || s.starts_with('\'');
486
487 if needs_quotes {
488 Ok(JsonnetValue::string(format!("\"{}\"", escaped)))
489 } else {
490 Ok(JsonnetValue::string(escaped))
491 }
492 }
493
494 fn escape_string_python(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
495 Self::check_args(&args, 1, "escapeStringPython")?;
496 let s = args[0].as_string()?;
497 let escaped = s.escape_default().to_string();
498 Ok(JsonnetValue::string(format!("'{}'", escaped)))
499 }
500
501 fn escape_string_bash(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
502 Self::check_args(&args, 1, "escapeStringBash")?;
503 let s = args[0].as_string()?;
504 let escaped = s.replace("'", "'\"'\"'").replace("\\", "\\\\");
505 Ok(JsonnetValue::string(format!("'{}'", escaped)))
506 }
507
508 fn escape_string_dollars(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
509 Self::check_args(&args, 1, "escapeStringDollars")?;
510 let s = args[0].as_string()?;
511 let escaped = s.replace("$$", "$").replace("$", "$$");
512 Ok(JsonnetValue::string(escaped))
513 }
514
515 fn string_chars(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
517 Self::check_args(&args, 1, "stringChars")?;
518 let s = args[0].as_string()?;
519 let chars: Vec<JsonnetValue> = s.chars().map(|c| JsonnetValue::string(c.to_string())).collect();
520 Ok(JsonnetValue::array(chars))
521 }
522
523 fn string_bytes(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
524 Self::check_args(&args, 1, "stringBytes")?;
525 let s = args[0].as_string()?;
526 let bytes: Vec<JsonnetValue> = s.as_bytes().iter().map(|&b| JsonnetValue::number(b as f64)).collect();
527 Ok(JsonnetValue::array(bytes))
528 }
529
530 fn format(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
531 Self::check_args(&args, 2, "format")?;
532 let format_str = args[0].as_string()?;
533 let values = args[1].as_array()?;
534
535 let mut result = format_str.to_string();
537 for (i, value) in values.iter().enumerate() {
538 let placeholder = format!("%{}", i + 1);
539 let value_str = match value {
540 JsonnetValue::String(s) => s.clone(),
541 JsonnetValue::Number(n) => n.to_string(),
542 JsonnetValue::Boolean(b) => b.to_string(),
543 _ => value.to_string(),
544 };
545 result = result.replace(&placeholder, &value_str);
546 }
547
548 Ok(JsonnetValue::string(result))
549 }
550
551 fn is_array(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
553 Self::check_args(&args, 1, "isArray")?;
554 Ok(JsonnetValue::boolean(matches!(args[0], JsonnetValue::Array(_))))
555 }
556
557 fn is_boolean(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
558 Self::check_args(&args, 1, "isBoolean")?;
559 Ok(JsonnetValue::boolean(matches!(args[0], JsonnetValue::Boolean(_))))
560 }
561
562 fn is_function(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
563 Self::check_args(&args, 1, "isFunction")?;
564 Ok(JsonnetValue::boolean(matches!(args[0], JsonnetValue::Function(_))))
565 }
566
567 fn is_number(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
568 Self::check_args(&args, 1, "isNumber")?;
569 Ok(JsonnetValue::boolean(matches!(args[0], JsonnetValue::Number(_))))
570 }
571
572 fn is_object(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
573 Self::check_args(&args, 1, "isObject")?;
574 Ok(JsonnetValue::boolean(matches!(args[0], JsonnetValue::Object(_))))
575 }
576
577 fn is_string(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
578 Self::check_args(&args, 1, "isString")?;
579 Ok(JsonnetValue::boolean(matches!(args[0], JsonnetValue::String(_))))
580 }
581
582 fn count(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
584 Self::check_args(&args, 2, "count")?;
585 let arr = args[0].as_array()?;
586 let elem = &args[1];
587 let count = arr.iter().filter(|item| item.equals(elem)).count() as f64;
588 Ok(JsonnetValue::number(count))
589 }
590
591 fn find(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
592 Self::check_args(&args, 2, "find")?;
593 match (&args[0], &args[1]) {
594 (JsonnetValue::Array(arr), value) => {
595 let mut indices = Vec::new();
596 for (i, item) in arr.iter().enumerate() {
597 if item == value {
598 indices.push(JsonnetValue::Number(i as f64));
599 }
600 }
601 Ok(JsonnetValue::array(indices))
602 }
603 _ => Err(JsonnetError::runtime_error("find expects array and search value")),
604 }
605 }
606
607 fn member(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
608 Self::contains(args)
609 }
610
611 fn modulo(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
613 Self::check_args(&args, 2, "modulo")?;
614 let a = args[0].as_number()?;
615 let b = args[1].as_number()?;
616 if b == 0.0 {
617 return Err(JsonnetError::DivisionByZero);
618 }
619 Ok(JsonnetValue::number(a % b))
620 }
621
622 fn pow(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
623 Self::check_args(&args, 2, "pow")?;
624 let a = args[0].as_number()?;
625 let b = args[1].as_number()?;
626 Ok(JsonnetValue::number(a.powf(b)))
627 }
628
629 fn exp(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
630 Self::check_args(&args, 1, "exp")?;
631 let x = args[0].as_number()?;
632 Ok(JsonnetValue::number(x.exp()))
633 }
634
635 fn log(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
636 Self::check_args(&args, 1, "log")?;
637 let x = args[0].as_number()?;
638 if x <= 0.0 {
639 return Err(JsonnetError::runtime_error("log of non-positive number"));
640 }
641 Ok(JsonnetValue::number(x.ln()))
642 }
643
644 fn sqrt(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
645 Self::check_args(&args, 1, "sqrt")?;
646 let x = args[0].as_number()?;
647 if x < 0.0 {
648 return Err(JsonnetError::runtime_error("sqrt of negative number"));
649 }
650 Ok(JsonnetValue::number(x.sqrt()))
651 }
652
653 fn sin(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
654 Self::check_args(&args, 1, "sin")?;
655 let x = args[0].as_number()?;
656 Ok(JsonnetValue::number(x.sin()))
657 }
658
659 fn cos(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
660 Self::check_args(&args, 1, "cos")?;
661 let x = args[0].as_number()?;
662 Ok(JsonnetValue::number(x.cos()))
663 }
664
665 fn tan(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
666 Self::check_args(&args, 1, "tan")?;
667 let x = args[0].as_number()?;
668 Ok(JsonnetValue::number(x.tan()))
669 }
670
671 fn asin(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
672 Self::check_args(&args, 1, "asin")?;
673 let x = args[0].as_number()?;
674 Ok(JsonnetValue::number(x.asin()))
675 }
676
677 fn acos(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
678 Self::check_args(&args, 1, "acos")?;
679 let x = args[0].as_number()?;
680 Ok(JsonnetValue::number(x.acos()))
681 }
682
683 fn atan(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
684 Self::check_args(&args, 1, "atan")?;
685 let x = args[0].as_number()?;
686 Ok(JsonnetValue::number(x.atan()))
687 }
688
689 fn floor(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
690 Self::check_args(&args, 1, "floor")?;
691 let x = args[0].as_number()?;
692 Ok(JsonnetValue::number(x.floor()))
693 }
694
695 fn ceil(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
696 Self::check_args(&args, 1, "ceil")?;
697 let x = args[0].as_number()?;
698 Ok(JsonnetValue::number(x.ceil()))
699 }
700
701 fn round(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
702 Self::check_args(&args, 1, "round")?;
703 let x = args[0].as_number()?;
704 Ok(JsonnetValue::number(x.round()))
705 }
706
707 fn abs(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
708 Self::check_args(&args, 1, "abs")?;
709 let x = args[0].as_number()?;
710 Ok(JsonnetValue::number(x.abs()))
711 }
712
713 fn max(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
714 Self::check_args(&args, 1, "max")?;
715 let arr = args[0].as_array()?;
716 if arr.is_empty() {
717 return Err(JsonnetError::runtime_error("max() called on empty array"));
718 }
719 let mut max_val = f64::NEG_INFINITY;
720 for item in arr {
721 let val = item.as_number()?;
722 if val > max_val {
723 max_val = val;
724 }
725 }
726 Ok(JsonnetValue::number(max_val))
727 }
728
729 fn min(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
730 Self::check_args(&args, 1, "min")?;
731 let arr = args[0].as_array()?;
732 if arr.is_empty() {
733 return Err(JsonnetError::runtime_error("min() called on empty array"));
734 }
735 let mut min_val = f64::INFINITY;
736 for item in arr {
737 let val = item.as_number()?;
738 if val < min_val {
739 min_val = val;
740 }
741 }
742 Ok(JsonnetValue::number(min_val))
743 }
744
745 fn clamp(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
746 Self::check_args(&args, 3, "clamp")?;
747 let x = args[0].as_number()?;
748 let min = args[1].as_number()?;
749 let max = args[2].as_number()?;
750 let clamped = x.max(min).min(max);
751 Ok(JsonnetValue::number(clamped))
752 }
753
754 fn assert_equal(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
755 Self::check_args(&args, 2, "assertEqual")?;
756 if !args[0].equals(&args[1]) {
757 return Err(JsonnetError::assertion_failed(format!(
758 "Assertion failed: {} != {}\n Left: {:?}\n Right: {:?}",
759 args[0], args[1], args[0], args[1]
760 )));
761 }
762 Ok(JsonnetValue::boolean(true))
763 }
764
765 fn trace(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
766 Self::check_args(&args, 2, "trace")?;
767 eprintln!("TRACE: {:?}", args[1]);
769 Ok(args[0].clone())
771 }
772
773 fn sort(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
775 Self::check_args(&args, 1, "sort")?;
776 let arr = args[0].as_array()?;
777
778 if arr.is_empty() {
779 return Ok(JsonnetValue::array(vec![]));
780 }
781
782 let mut sorted = arr.clone();
785 sorted.sort_by(|a, b| Self::compare_values(a, b));
786
787 Ok(JsonnetValue::array(sorted))
788 }
789
790 fn compare_values(a: &JsonnetValue, b: &JsonnetValue) -> std::cmp::Ordering {
791 match (a, b) {
792 (JsonnetValue::Null, JsonnetValue::Null) => std::cmp::Ordering::Equal,
793 (JsonnetValue::Null, _) => std::cmp::Ordering::Less,
794 (_, JsonnetValue::Null) => std::cmp::Ordering::Greater,
795 (JsonnetValue::Boolean(x), JsonnetValue::Boolean(y)) => x.cmp(y),
796 (JsonnetValue::Boolean(_), _) => std::cmp::Ordering::Less,
797 (_, JsonnetValue::Boolean(_)) => std::cmp::Ordering::Greater,
798 (JsonnetValue::Number(x), JsonnetValue::Number(y)) => {
799 x.partial_cmp(y).unwrap_or(std::cmp::Ordering::Equal)
800 }
801 (JsonnetValue::Number(_), _) => std::cmp::Ordering::Less,
802 (_, JsonnetValue::Number(_)) => std::cmp::Ordering::Greater,
803 (JsonnetValue::String(x), JsonnetValue::String(y)) => x.cmp(y),
804 (JsonnetValue::String(_), _) => std::cmp::Ordering::Less,
805 (_, JsonnetValue::String(_)) => std::cmp::Ordering::Greater,
806 (JsonnetValue::Array(x), JsonnetValue::Array(y)) => {
807 for (_i, (a_item, b_item)) in x.iter().zip(y.iter()).enumerate() {
808 let cmp = Self::compare_values(a_item, b_item);
809 if cmp != std::cmp::Ordering::Equal {
810 return cmp;
811 }
812 }
813 x.len().cmp(&y.len())
814 }
815 (JsonnetValue::Array(_), _) => std::cmp::Ordering::Less,
816 (_, JsonnetValue::Array(_)) => std::cmp::Ordering::Greater,
817 (JsonnetValue::Object(x), JsonnetValue::Object(y)) => {
818 let mut x_keys: Vec<_> = x.keys().collect();
820 let mut y_keys: Vec<_> = y.keys().collect();
821 x_keys.sort();
822 y_keys.sort();
823
824 for (x_key, y_key) in x_keys.iter().zip(y_keys.iter()) {
825 let key_cmp = x_key.cmp(y_key);
826 if key_cmp != std::cmp::Ordering::Equal {
827 return key_cmp;
828 }
829 if let (Some(x_val), Some(y_val)) = (x.get(*x_key), y.get(*y_key)) {
830 let val_cmp = Self::compare_values(x_val, y_val);
831 if val_cmp != std::cmp::Ordering::Equal {
832 return val_cmp;
833 }
834 }
835 }
836 x.len().cmp(&y.len())
837 }
838 _ => std::cmp::Ordering::Equal, }
840 }
841
842 fn uniq(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
843 Self::check_args(&args, 1, "uniq")?;
844 let arr = args[0].as_array()?;
845
846 let mut result: Vec<JsonnetValue> = Vec::new();
847 for item in arr {
848 let mut found = false;
850 for existing in &result {
851 if existing.equals(item) {
852 found = true;
853 break;
854 }
855 }
856 if !found {
857 result.push(item.clone());
858 }
859 }
860
861 Ok(JsonnetValue::array(result))
862 }
863
864 fn reverse(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
865 Self::check_args(&args, 1, "reverse")?;
866 let arr = args[0].as_array()?;
867 let reversed: Vec<JsonnetValue> = arr.iter().rev().cloned().collect();
868 Ok(JsonnetValue::array(reversed))
869 }
870
871 fn merge_patch(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
873 Self::check_args(&args, 2, "mergePatch")?;
874 let target = args[0].as_object()?;
875 let patch = args[1].as_object()?;
876
877 let mut result = target.clone();
878
879 for (key, patch_value) in patch {
880 match patch_value {
881 JsonnetValue::Null => {
882 result.remove(key);
884 }
885 JsonnetValue::Object(patch_obj) => {
886 if let Some(JsonnetValue::Object(target_obj)) = result.get(key) {
888 let merged = Self::merge_patch(vec![
889 JsonnetValue::object(target_obj.clone()),
890 JsonnetValue::object(patch_obj.clone())
891 ])?;
892 if let JsonnetValue::Object(merged_obj) = merged {
893 result.insert(key.clone(), JsonnetValue::object(merged_obj));
894 }
895 } else {
896 result.insert(key.clone(), JsonnetValue::object(patch_obj.clone()));
898 }
899 }
900 _ => {
901 result.insert(key.clone(), patch_value.clone());
903 }
904 }
905 }
906
907 Ok(JsonnetValue::object(result))
908 }
909
910 fn get(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
911 Self::check_args(&args, 3, "get")?;
912 let obj = args[0].as_object()?;
913 let key = args[1].as_string()?;
914 let default = &args[2];
915 Ok(obj.get(key).unwrap_or(default).clone())
916 }
917
918 fn object_fields(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
919 Self::check_args(&args, 1, "objectFields")?;
920 let obj = args[0].as_object()?;
921 let fields: Vec<JsonnetValue> = obj.keys()
922 .filter(|&k| !k.starts_with('_')) .map(|k| JsonnetValue::string(k.clone()))
924 .collect();
925 Ok(JsonnetValue::array(fields))
926 }
927
928 fn object_fields_all(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
929 Self::check_args(&args, 1, "objectFieldsAll")?;
930 let obj = args[0].as_object()?;
931 let fields: Vec<JsonnetValue> = obj.keys()
932 .map(|k| JsonnetValue::string(k.clone()))
933 .collect();
934 Ok(JsonnetValue::array(fields))
935 }
936
937 fn object_has(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
938 Self::check_args(&args, 2, "objectHas")?;
939 let obj = args[0].as_object()?;
940 let key = args[1].as_string()?;
941 Ok(JsonnetValue::boolean(obj.contains_key(key) && !key.starts_with('_')))
942 }
943
944 fn object_has_all(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
945 Self::check_args(&args, 2, "objectHasAll")?;
946 let obj = args[0].as_object()?;
947 let key = args[1].as_string()?;
948 Ok(JsonnetValue::boolean(obj.contains_key(key)))
949 }
950
951 fn object_values(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
952 Self::check_args(&args, 1, "objectValues")?;
953 let obj = args[0].as_object()?;
954 let values: Vec<JsonnetValue> = obj.iter()
955 .filter(|(k, _)| !k.starts_with('_'))
956 .map(|(_, v)| v.clone())
957 .collect();
958 Ok(JsonnetValue::array(values))
959 }
960
961 fn object_values_all(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
962 Self::check_args(&args, 1, "objectValuesAll")?;
963 let obj = args[0].as_object()?;
964 let values: Vec<JsonnetValue> = obj.values().cloned().collect();
965 Ok(JsonnetValue::array(values))
966 }
967
968 fn prune(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
969 Self::check_args(&args, 1, "prune")?;
970 Self::prune_value(&args[0])
971 }
972
973 fn prune_value(value: &JsonnetValue) -> Result<JsonnetValue> {
974 match value {
975 JsonnetValue::Null => Ok(JsonnetValue::Null),
976 JsonnetValue::Array(arr) => {
977 let pruned: Vec<JsonnetValue> = arr.iter()
978 .map(|item| Self::prune_value(item))
979 .collect::<Result<Vec<_>>>()?
980 .into_iter()
981 .filter(|item| !matches!(item, JsonnetValue::Null))
982 .collect();
983 Ok(JsonnetValue::array(pruned))
984 }
985 JsonnetValue::Object(obj) => {
986 let mut pruned_obj = HashMap::new();
987 for (key, val) in obj {
988 let pruned_val = Self::prune_value(val)?;
989 if !matches!(pruned_val, JsonnetValue::Null) {
990 pruned_obj.insert(key.clone(), pruned_val);
991 }
992 }
993 Ok(JsonnetValue::object(pruned_obj))
994 }
995 _ => Ok(value.clone()),
996 }
997 }
998
999 fn map_with_key(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1000 Self::check_args(&args, 2, "mapWithKey")?;
1001 let _func = &args[0];
1002 let obj = args[1].as_object()?;
1003
1004 let mut result = HashMap::new();
1007 for (key, value) in obj {
1008 if !key.starts_with('_') {
1009 result.insert(key.clone(), JsonnetValue::array(vec![
1012 JsonnetValue::string(key.clone()),
1013 value.clone()
1014 ]));
1015 }
1016 }
1017
1018 Ok(JsonnetValue::object(result))
1019 }
1020
1021 fn object_fields_ex(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1022 Self::check_args(&args, 2, "objectFieldsEx")?;
1023 let obj = args[0].as_object()?;
1024 let include_hidden = args[1].as_boolean()?;
1025
1026 let fields: Vec<JsonnetValue> = obj.keys()
1027 .filter(|&k| include_hidden || !k.starts_with('_'))
1028 .map(|k| JsonnetValue::string(k.clone()))
1029 .collect();
1030
1031 Ok(JsonnetValue::array(fields))
1032 }
1033
1034 fn object_values_ex(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1035 Self::check_args(&args, 2, "objectValuesEx")?;
1036 let obj = args[0].as_object()?;
1037 let include_hidden = args[1].as_boolean()?;
1038
1039 let values: Vec<JsonnetValue> = obj.iter()
1040 .filter(|(k, _)| include_hidden || !k.starts_with('_'))
1041 .map(|(_, v)| v.clone())
1042 .collect();
1043
1044 Ok(JsonnetValue::array(values))
1045 }
1046
1047 fn to_lower(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1048 Self::check_args(&args, 1, "toLower")?;
1049 match &args[0] {
1050 JsonnetValue::String(s) => Ok(JsonnetValue::string(s.to_lowercase())),
1051 _ => Err(JsonnetError::runtime_error("toLower expects a string argument")),
1052 }
1053 }
1054
1055 fn to_upper(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1056 Self::check_args(&args, 1, "toUpper")?;
1057 match &args[0] {
1058 JsonnetValue::String(s) => Ok(JsonnetValue::string(s.to_uppercase())),
1059 _ => Err(JsonnetError::runtime_error("toUpper expects a string argument")),
1060 }
1061 }
1062
1063 fn trim(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1064 Self::check_args(&args, 1, "trim")?;
1065 match &args[0] {
1066 JsonnetValue::String(s) => Ok(JsonnetValue::string(s.trim().to_string())),
1067 _ => Err(JsonnetError::runtime_error("trim expects a string argument")),
1068 }
1069 }
1070
1071 fn all(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1072 Self::check_args(&args, 1, "all")?;
1073 match &args[0] {
1074 JsonnetValue::Array(arr) => {
1075 let result = arr.iter().all(|item| item.is_truthy());
1076 Ok(JsonnetValue::boolean(result))
1077 }
1078 _ => Err(JsonnetError::runtime_error("all expects an array argument")),
1079 }
1080 }
1081
1082 fn any(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1083 Self::check_args(&args, 1, "any")?;
1084 match &args[0] {
1085 JsonnetValue::Array(arr) => {
1086 let result = arr.iter().any(|item| item.is_truthy());
1087 Ok(JsonnetValue::boolean(result))
1088 }
1089 _ => Err(JsonnetError::runtime_error("any expects an array argument")),
1090 }
1091 }
1092
1093 fn id(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1094 Self::check_args(&args, 1, "id")?;
1095 Ok(args[0].clone())
1096 }
1097
1098 fn equals(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1099 Self::check_args(&args, 2, "equals")?;
1100 let a = &args[0];
1101 let b = &args[1];
1102
1103 if a == b {
1105 return Ok(JsonnetValue::boolean(true));
1106 }
1107
1108 let ta = a.type_name();
1110 let tb = b.type_name();
1111 if ta != tb {
1112 return Ok(JsonnetValue::boolean(false));
1113 }
1114
1115 match (a, b) {
1116 (JsonnetValue::Array(arr_a), JsonnetValue::Array(arr_b)) => {
1117 if arr_a.len() != arr_b.len() {
1118 return Ok(JsonnetValue::boolean(false));
1119 }
1120 for (i, item_a) in arr_a.iter().enumerate() {
1121 let eq_args = vec![item_a.clone(), arr_b[i].clone()];
1122 if let Ok(JsonnetValue::Boolean(false)) = Self::equals(eq_args) {
1123 return Ok(JsonnetValue::boolean(false));
1124 }
1125 }
1126 Ok(JsonnetValue::boolean(true))
1127 }
1128 (JsonnetValue::Object(obj_a), JsonnetValue::Object(obj_b)) => {
1129 let fields_a: Vec<String> = obj_a.keys().cloned().collect();
1131 let fields_b: Vec<String> = obj_b.keys().cloned().collect();
1132
1133 if fields_a.len() != fields_b.len() {
1134 return Ok(JsonnetValue::boolean(false));
1135 }
1136
1137 let mut sorted_a = fields_a.clone();
1139 sorted_a.sort();
1140 let mut sorted_b = fields_b.clone();
1141 sorted_b.sort();
1142
1143 if sorted_a != sorted_b {
1144 return Ok(JsonnetValue::boolean(false));
1145 }
1146
1147 for field in sorted_a {
1149 let val_a = &obj_a[&field];
1150 let val_b = &obj_b[&field];
1151 let eq_args = vec![val_a.clone(), val_b.clone()];
1152 if let Ok(JsonnetValue::Boolean(false)) = Self::equals(eq_args) {
1153 return Ok(JsonnetValue::boolean(false));
1154 }
1155 }
1156 Ok(JsonnetValue::boolean(true))
1157 }
1158 _ => Ok(JsonnetValue::boolean(false)),
1159 }
1160 }
1161
1162 fn lines(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1163 Self::check_args(&args, 1, "lines")?;
1164 match &args[0] {
1165 JsonnetValue::Array(arr) => {
1166 let mut lines = Vec::new();
1167 for item in arr {
1168 match item {
1170 JsonnetValue::String(s) => lines.push(s.clone()),
1171 JsonnetValue::Number(n) => lines.push(n.to_string()),
1172 JsonnetValue::Boolean(b) => lines.push(b.to_string()),
1173 _ => lines.push(format!("{}", item)),
1174 }
1175 }
1176 lines.push("".to_string()); Ok(JsonnetValue::string(lines.join("\n")))
1178 }
1179 _ => Err(JsonnetError::runtime_error("lines expects an array argument")),
1180 }
1181 }
1182
1183 fn str_replace(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1184 Self::check_args(&args, 3, "strReplace")?;
1185
1186 let str_val = &args[0];
1187 let from_val = &args[1];
1188 let to_val = &args[2];
1189
1190 let str = str_val.as_string()?.to_string();
1191 let from = from_val.as_string()?.to_string();
1192 let to = to_val.as_string()?.to_string();
1193
1194 if from.is_empty() {
1195 return Err(JsonnetError::runtime_error("'from' string must not be zero length"));
1196 }
1197
1198 let result = str.replace(&from, &to);
1202 Ok(JsonnetValue::string(result))
1203 }
1204
1205 fn sha1(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1206 Self::check_args(&args, 1, "sha1")?;
1207 let input = args[0].as_string()?.as_bytes();
1208 let mut hasher = Sha1::new();
1209 hasher.update(input);
1210 let result = hasher.finalize();
1211 Ok(JsonnetValue::string(hex::encode(result)))
1212 }
1213
1214 fn sha256(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1215 Self::check_args(&args, 1, "sha256")?;
1216 let input = args[0].as_string()?.as_bytes();
1217 let mut hasher = Sha256::new();
1218 hasher.update(input);
1219 let result = hasher.finalize();
1220 Ok(JsonnetValue::string(hex::encode(result)))
1221 }
1222
1223 fn sha3(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1224 Self::check_args(&args, 1, "sha3")?;
1225 let input = args[0].as_string()?.as_bytes();
1226 let mut hasher = Sha3_256::new();
1227 hasher.update(input);
1228 let result = hasher.finalize();
1229 Ok(JsonnetValue::string(hex::encode(result)))
1230 }
1231
1232 fn sha512(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1233 Self::check_args(&args, 1, "sha512")?;
1234 let input = args[0].as_string()?.as_bytes();
1235 let mut hasher = Sha512::new();
1236 hasher.update(input);
1237 let result = hasher.finalize();
1238 Ok(JsonnetValue::string(hex::encode(result)))
1239 }
1240
1241 fn ascii_lower(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1242 Self::check_args(&args, 1, "asciiLower")?;
1243 let input = args[0].as_string()?;
1244 Ok(JsonnetValue::string(input.to_ascii_lowercase()))
1245 }
1246
1247 fn ascii_upper(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1248 Self::check_args(&args, 1, "asciiUpper")?;
1249 let input = args[0].as_string()?;
1250 Ok(JsonnetValue::string(input.to_ascii_uppercase()))
1251 }
1252
1253 fn flat_map(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1254 Self::check_args(&args, 2, "flatMap")?;
1255 let func = &args[0];
1256 let arr = &args[1];
1257
1258 match arr {
1259 JsonnetValue::Array(array) => {
1260 let mut result = Vec::new();
1261 for item in array {
1262 if let JsonnetValue::Array(sub_array) = item {
1266 result.extend(sub_array.clone());
1267 } else {
1268 result.push(item.clone());
1269 }
1270 }
1271 Ok(JsonnetValue::array(result))
1272 }
1273 JsonnetValue::String(s) => {
1274 let mut result = Vec::new();
1276 for ch in s.chars() {
1277 result.push(JsonnetValue::string(ch.to_string()));
1279 }
1280 Ok(JsonnetValue::array(result))
1281 }
1282 _ => Err(JsonnetError::runtime_error("flatMap expects array or string as second argument")),
1283 }
1284 }
1285
1286 fn map_with_index(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1287 Self::check_args(&args, 2, "mapWithIndex")?;
1288 let func = &args[0];
1289 let arr = &args[1];
1290
1291 match arr {
1292 JsonnetValue::Array(array) => {
1293 let mut result = Vec::new();
1294 for (i, item) in array.iter().enumerate() {
1295 result.push(JsonnetValue::array(vec![JsonnetValue::number(i as f64), item.clone()]));
1298 }
1299 Ok(JsonnetValue::array(result))
1300 }
1301 JsonnetValue::String(s) => {
1302 let mut result = Vec::new();
1303 for (i, ch) in s.chars().enumerate() {
1304 result.push(JsonnetValue::array(vec![
1305 JsonnetValue::number(i as f64),
1306 JsonnetValue::string(ch.to_string())
1307 ]));
1308 }
1309 Ok(JsonnetValue::array(result))
1310 }
1311 _ => Err(JsonnetError::runtime_error("mapWithIndex expects array or string as second argument")),
1312 }
1313 }
1314
1315 fn lstrip_chars(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1316 Self::check_args(&args, 2, "lstripChars")?;
1317 let str_val = args[0].as_string()?;
1318 let chars_val = args[1].as_string()?;
1319
1320 let chars_set: std::collections::HashSet<char> = chars_val.chars().collect();
1321 let result: String = str_val.chars()
1322 .skip_while(|c| chars_set.contains(c))
1323 .collect();
1324
1325 Ok(JsonnetValue::string(result))
1326 }
1327
1328 fn rstrip_chars(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1329 Self::check_args(&args, 2, "rstripChars")?;
1330 let str_val = args[0].as_string()?;
1331 let chars_val = args[1].as_string()?;
1332
1333 let chars_set: std::collections::HashSet<char> = chars_val.chars().collect();
1334 let result: String = str_val.chars()
1335 .rev()
1336 .skip_while(|c| chars_set.contains(c))
1337 .collect::<Vec<char>>()
1338 .into_iter()
1339 .rev()
1340 .collect();
1341
1342 Ok(JsonnetValue::string(result))
1343 }
1344
1345 fn strip_chars(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1346 Self::check_args(&args, 2, "stripChars")?;
1347 let str_val = &args[0];
1348 let chars_val = &args[1];
1349
1350 let lstripped_args = vec![str_val.clone(), chars_val.clone()];
1352 let lstripped = Self::lstrip_chars(lstripped_args)?;
1353 let rstripped_args = vec![lstripped, chars_val.clone()];
1354 Self::rstrip_chars(rstripped_args)
1355 }
1356
1357 fn find_substr(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1358 Self::check_args(&args, 2, "findSubstr")?;
1359 let pat = args[0].as_string()?;
1360 let str = args[1].as_string()?;
1361
1362 if pat.is_empty() {
1363 return Err(JsonnetError::runtime_error("findSubstr pattern cannot be empty"));
1364 }
1365
1366 let mut result = Vec::new();
1367 let mut start = 0;
1368
1369 while let Some(pos) = str[start..].find(&pat) {
1370 result.push(JsonnetValue::number((start + pos) as f64));
1371 start += pos + pat.len();
1372 }
1373
1374 Ok(JsonnetValue::array(result))
1375 }
1376
1377 fn repeat(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1378 Self::check_args(&args, 2, "repeat")?;
1379 let what = &args[0];
1380 let count_val = &args[1];
1381
1382 let count = if let JsonnetValue::Number(n) = count_val {
1383 *n as usize
1384 } else {
1385 return Err(JsonnetError::runtime_error("repeat count must be a number"));
1386 };
1387
1388 match what {
1389 JsonnetValue::String(s) => {
1390 let repeated = s.repeat(count);
1391 Ok(JsonnetValue::string(repeated))
1392 }
1393 JsonnetValue::Array(arr) => {
1394 let mut result = Vec::new();
1395 for _ in 0..count {
1396 result.extend(arr.clone());
1397 }
1398 Ok(JsonnetValue::array(result))
1399 }
1400 _ => Err(JsonnetError::runtime_error("repeat first argument must be string or array")),
1401 }
1402 }
1403
1404 fn set(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1405 Self::check_args(&args, 1, "set")?;
1406 match &args[0] {
1407 JsonnetValue::Array(arr) => {
1408 let mut result = Vec::new();
1410
1411 for item in arr {
1412 let mut found = false;
1414 for existing in &result {
1415 if existing == item {
1416 found = true;
1417 break;
1418 }
1419 }
1420 if !found {
1421 result.push(item.clone());
1422 }
1423 }
1424
1425 Ok(JsonnetValue::array(result))
1426 }
1427 _ => Err(JsonnetError::runtime_error("set expects an array argument")),
1428 }
1429 }
1430
1431 fn set_member(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1432 Self::check_args(&args, 2, "setMember")?;
1433 let value = &args[0];
1434 let arr = match &args[1] {
1435 JsonnetValue::Array(a) => a,
1436 _ => return Err(JsonnetError::runtime_error("setMember expects array as second argument")),
1437 };
1438
1439 for item in arr {
1440 if item == value {
1441 return Ok(JsonnetValue::boolean(true));
1442 }
1443 }
1444 Ok(JsonnetValue::boolean(false))
1445 }
1446
1447 fn set_union(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1448 Self::check_args(&args, 2, "setUnion")?;
1449 let arr_a = match &args[0] {
1450 JsonnetValue::Array(a) => a,
1451 _ => return Err(JsonnetError::runtime_error("setUnion expects arrays as arguments")),
1452 };
1453 let arr_b = match &args[1] {
1454 JsonnetValue::Array(a) => a,
1455 _ => return Err(JsonnetError::runtime_error("setUnion expects arrays as arguments")),
1456 };
1457
1458 let mut result = Vec::new();
1459
1460 for item in arr_a {
1462 let mut found = false;
1463 for existing in &result {
1464 if existing == item {
1465 found = true;
1466 break;
1467 }
1468 }
1469 if !found {
1470 result.push(item.clone());
1471 }
1472 }
1473
1474 for item in arr_b {
1476 let mut found = false;
1477 for existing in &result {
1478 if existing == item {
1479 found = true;
1480 break;
1481 }
1482 }
1483 if !found {
1484 result.push(item.clone());
1485 }
1486 }
1487
1488 Ok(JsonnetValue::array(result))
1489 }
1490
1491 fn set_inter(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1492 Self::check_args(&args, 2, "setInter")?;
1493 let arr_a = match &args[0] {
1494 JsonnetValue::Array(a) => a,
1495 _ => return Err(JsonnetError::runtime_error("setInter expects arrays as arguments")),
1496 };
1497 let arr_b = match &args[1] {
1498 JsonnetValue::Array(a) => a,
1499 _ => return Err(JsonnetError::runtime_error("setInter expects arrays as arguments")),
1500 };
1501
1502 let mut result = Vec::new();
1503
1504 for item_a in arr_a {
1505 let mut found_in_b = false;
1507 for item_b in arr_b {
1508 if item_a == item_b {
1509 found_in_b = true;
1510 break;
1511 }
1512 }
1513
1514 if found_in_b {
1515 let mut already_in_result = false;
1517 for existing in &result {
1518 if existing == item_a {
1519 already_in_result = true;
1520 break;
1521 }
1522 }
1523 if !already_in_result {
1524 result.push(item_a.clone());
1525 }
1526 }
1527 }
1528
1529 Ok(JsonnetValue::array(result))
1530 }
1531
1532 fn set_diff(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1533 Self::check_args(&args, 2, "setDiff")?;
1534 let arr_a = match &args[0] {
1535 JsonnetValue::Array(a) => a,
1536 _ => return Err(JsonnetError::runtime_error("setDiff expects arrays as arguments")),
1537 };
1538 let arr_b = match &args[1] {
1539 JsonnetValue::Array(a) => a,
1540 _ => return Err(JsonnetError::runtime_error("setDiff expects arrays as arguments")),
1541 };
1542
1543 let mut result = Vec::new();
1544
1545 for item_a in arr_a {
1546 let mut found_in_b = false;
1548 for item_b in arr_b {
1549 if item_a == item_b {
1550 found_in_b = true;
1551 break;
1552 }
1553 }
1554
1555 if !found_in_b {
1556 let mut already_in_result = false;
1558 for existing in &result {
1559 if existing == item_a {
1560 already_in_result = true;
1561 break;
1562 }
1563 }
1564 if !already_in_result {
1565 result.push(item_a.clone());
1566 }
1567 }
1568 }
1569
1570 Ok(JsonnetValue::array(result))
1571 }
1572
1573 fn manifest_ini(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1577 Self::check_args(&args, 1, "manifestIni")?;
1578 match &args[0] {
1580 JsonnetValue::Object(obj) => {
1581 let mut result = String::new();
1582 for (key, value) in obj {
1583 if !key.starts_with('_') {
1584 result.push_str(&format!("[{}]\n", key));
1585 if let JsonnetValue::Object(section) = value {
1586 for (k, v) in section {
1587 if !k.starts_with('_') {
1588 result.push_str(&format!("{}={}\n", k, v));
1589 }
1590 }
1591 }
1592 result.push('\n');
1593 }
1594 }
1595 Ok(JsonnetValue::string(result.trim().to_string()))
1596 }
1597 _ => Err(JsonnetError::runtime_error("manifestIni expects an object")),
1598 }
1599 }
1600
1601 fn manifest_python(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1602 Self::check_args(&args, 1, "manifestPython")?;
1603 let json_str = serde_json::to_string(&args[0].to_json_value())?;
1605 let python_str = json_str
1607 .replace("null", "None")
1608 .replace("true", "True")
1609 .replace("false", "False");
1610 Ok(JsonnetValue::string(python_str))
1611 }
1612
1613 fn manifest_cpp(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1614 Self::check_args(&args, 1, "manifestCpp")?;
1615 let json_str = serde_json::to_string(&args[0].to_json_value())?;
1617 let cpp_str = format!("// Generated C++ code\nconst char* jsonData = R\"json(\n{}\n)json\";", json_str);
1618 Ok(JsonnetValue::string(cpp_str))
1619 }
1620
1621 fn manifest_xml_jsonml(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1622 Self::check_args(&args, 1, "manifestXmlJsonml")?;
1623 match &args[0] {
1625 JsonnetValue::Array(arr) if !arr.is_empty() => {
1626 if let JsonnetValue::String(tag) = &arr[0] {
1627 let mut xml = format!("<{}", tag);
1628
1629 let mut child_start = 1;
1631 if arr.len() > 1 {
1632 if let JsonnetValue::Object(attrs) = &arr[1] {
1633 for (key, value) in attrs {
1634 if !key.starts_with('_') {
1635 let value_str = match value {
1636 JsonnetValue::String(s) => s.clone(),
1637 _ => format!("{}", value),
1638 };
1639 xml.push_str(&format!(" {}=\"{}\"", key, value_str));
1640 }
1641 }
1642 child_start = 2;
1643 }
1644 }
1645
1646 xml.push('>');
1647
1648 for child in &arr[child_start..] {
1650 match child {
1651 JsonnetValue::String(s) => xml.push_str(s),
1652 JsonnetValue::Array(_) => {
1653 let child_xml = Self::manifest_xml_jsonml(vec![child.clone()])?;
1655 if let JsonnetValue::String(child_str) = child_xml {
1656 xml.push_str(&child_str);
1657 }
1658 }
1659 _ => xml.push_str(&format!("{}", child)),
1660 }
1661 }
1662
1663 xml.push_str(&format!("</{}>", tag));
1664 Ok(JsonnetValue::string(xml))
1665 } else {
1666 Err(JsonnetError::runtime_error("JsonML array must start with string tag name"))
1667 }
1668 }
1669 _ => Err(JsonnetError::runtime_error("manifestXmlJsonml expects a JsonML array")),
1670 }
1671 }
1672
1673 fn log2(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1675 Self::check_args(&args, 1, "log2")?;
1676 let x = args[0].as_number()?;
1677 if x <= 0.0 {
1678 return Err(JsonnetError::runtime_error("log2 of non-positive number"));
1679 }
1680 Ok(JsonnetValue::number(x.log2()))
1681 }
1682
1683 fn log10(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1684 Self::check_args(&args, 1, "log10")?;
1685 let x = args[0].as_number()?;
1686 if x <= 0.0 {
1687 return Err(JsonnetError::runtime_error("log10 of non-positive number"));
1688 }
1689 Ok(JsonnetValue::number(x.log10()))
1690 }
1691
1692 fn log1p(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1693 Self::check_args(&args, 1, "log1p")?;
1694 let x = args[0].as_number()?;
1695 if x < -1.0 {
1696 return Err(JsonnetError::runtime_error("log1p of number less than -1"));
1697 }
1698 Ok(JsonnetValue::number((x + 1.0).ln()))
1699 }
1700
1701 fn expm1(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1702 Self::check_args(&args, 1, "expm1")?;
1703 let x = args[0].as_number()?;
1704 Ok(JsonnetValue::number(x.exp() - 1.0))
1705 }
1706
1707 fn remove(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1711 Self::check_args(&args, 2, "remove")?;
1712 let arr = args[0].as_array()?;
1713 let value_to_remove = &args[1];
1714
1715 let filtered: Vec<JsonnetValue> = arr.iter()
1716 .filter(|item| !item.equals(value_to_remove))
1717 .cloned()
1718 .collect();
1719
1720 Ok(JsonnetValue::array(filtered))
1721 }
1722
1723 fn remove_at(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1724 Self::check_args(&args, 2, "removeAt")?;
1725 let arr = args[0].as_array()?;
1726 let index = args[1].as_number()? as usize;
1727
1728 if index >= arr.len() {
1729 return Err(JsonnetError::runtime_error("Index out of bounds"));
1730 }
1731
1732 let mut result = arr.clone();
1733 result.remove(index);
1734 Ok(JsonnetValue::array(result))
1735 }
1736
1737 fn flatten_arrays(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1738 Self::check_args(&args, 1, "flattenArrays")?;
1739 let arr = args[0].as_array()?;
1740
1741 let mut result = Vec::new();
1742 Self::flatten_array_recursive(arr, &mut result);
1743 Ok(JsonnetValue::array(result))
1744 }
1745
1746 fn flatten_array_recursive(arr: &[JsonnetValue], result: &mut Vec<JsonnetValue>) {
1747 for item in arr {
1748 match item {
1749 JsonnetValue::Array(sub_arr) => {
1750 Self::flatten_array_recursive(sub_arr, result);
1751 }
1752 _ => result.push(item.clone()),
1753 }
1754 }
1755 }
1756
1757 fn object_keys_values(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1759 Self::check_args(&args, 1, "objectKeysValues")?;
1760 let obj = args[0].as_object()?;
1761
1762 let mut result = Vec::new();
1763 for (key, value) in obj {
1764 if !key.starts_with('_') {
1765 result.push(JsonnetValue::object(HashMap::from([
1766 ("key".to_string(), JsonnetValue::string(key.clone())),
1767 ("value".to_string(), value.clone()),
1768 ])));
1769 }
1770 }
1771
1772 Ok(JsonnetValue::array(result))
1773 }
1774
1775 fn object_remove_key(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1776 Self::check_args(&args, 2, "objectRemoveKey")?;
1777 let obj = args[0].as_object()?;
1778 let key_to_remove = args[1].as_string()?;
1779
1780 let mut result = obj.clone();
1781 result.remove(key_to_remove);
1782 Ok(JsonnetValue::object(result))
1783 }
1784
1785 fn is_integer(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1787 Self::check_args(&args, 1, "isInteger")?;
1788 match &args[0] {
1789 JsonnetValue::Number(n) => Ok(JsonnetValue::boolean(n.fract() == 0.0)),
1790 _ => Ok(JsonnetValue::boolean(false)),
1791 }
1792 }
1793
1794 fn is_decimal(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1795 Self::check_args(&args, 1, "isDecimal")?;
1796 match &args[0] {
1797 JsonnetValue::Number(n) => Ok(JsonnetValue::boolean(n.fract() != 0.0)),
1798 _ => Ok(JsonnetValue::boolean(false)),
1799 }
1800 }
1801
1802 fn is_even(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1803 Self::check_args(&args, 1, "isEven")?;
1804 match &args[0] {
1805 JsonnetValue::Number(n) if n.fract() == 0.0 => {
1806 Ok(JsonnetValue::boolean((*n as i64) % 2 == 0))
1807 }
1808 _ => Ok(JsonnetValue::boolean(false)),
1809 }
1810 }
1811
1812 fn is_odd(args: Vec<JsonnetValue>) -> Result<JsonnetValue> {
1813 Self::check_args(&args, 1, "isOdd")?;
1814 match &args[0] {
1815 JsonnetValue::Number(n) if n.fract() == 0.0 => {
1816 Ok(JsonnetValue::boolean((*n as i64) % 2 != 0))
1817 }
1818 _ => Ok(JsonnetValue::boolean(false)),
1819 }
1820 }
1821
1822 fn check_args(args: &[JsonnetValue], expected: usize, func_name: &str) -> Result<()> {
1824 if args.len() != expected {
1825 return Err(JsonnetError::invalid_function_call(format!(
1826 "{}() expects {} arguments, got {}",
1827 func_name, expected, args.len()
1828 )));
1829 }
1830 Ok(())
1831 }
1832}
1833
1834impl JsonnetValue {
1835 pub fn from_json_value(value: serde_json::Value) -> Self {
1837 match value {
1838 serde_json::Value::Null => JsonnetValue::Null,
1839 serde_json::Value::Bool(b) => JsonnetValue::boolean(b),
1840 serde_json::Value::Number(n) => JsonnetValue::number(n.as_f64().unwrap_or(0.0)),
1841 serde_json::Value::String(s) => JsonnetValue::string(s),
1842 serde_json::Value::Array(arr) => {
1843 let jsonnet_arr: Vec<JsonnetValue> = arr.into_iter()
1844 .map(JsonnetValue::from_json_value)
1845 .collect();
1846 JsonnetValue::array(jsonnet_arr)
1847 }
1848 serde_json::Value::Object(obj) => {
1849 let mut jsonnet_obj = HashMap::new();
1850 for (k, v) in obj {
1851 jsonnet_obj.insert(k, JsonnetValue::from_json_value(v));
1852 }
1853 JsonnetValue::object(jsonnet_obj)
1854 }
1855 }
1856 }
1857}