1use std::collections::HashSet;
4
5use serde_json::{Number, Value};
6
7use crate::ast::Ast;
8use crate::functions::{Function, custom_error};
9use crate::interpreter::{SearchResult, interpret};
10use crate::registry::register_if_enabled;
11use crate::{Context, Runtime, arg, defn, get_expref_id};
12
13fn get_expref_ast<'a>(value: &Value, ctx: &'a Context<'_>) -> Option<&'a Ast> {
15 get_expref_id(value).and_then(|id| ctx.get_expref(id))
16}
17
18fn value_to_key(value: &Value) -> String {
20 match value {
21 Value::String(s) => s.clone(),
22 Value::Number(n) => n.to_string(),
23 Value::Bool(b) => b.to_string(),
24 Value::Null => "null".to_string(),
25 _ => serde_json::to_string(value).unwrap_or_default(),
26 }
27}
28
29fn extract_key(
33 item: &Value,
34 second_arg: &Value,
35 ctx: &mut Context<'_>,
36) -> Result<Option<String>, crate::error::JmespathError> {
37 if let Some(ast) = get_expref_ast(second_arg, ctx) {
38 let ast = ast.clone();
39 let key_val = interpret(item, &ast, ctx)?;
40 Ok(Some(value_to_key(&key_val)))
41 } else if let Some(field_name) = second_arg.as_str() {
42 if let Some(obj) = item.as_object() {
43 if let Some(field_value) = obj.get(field_name) {
44 Ok(Some(value_to_key(field_value)))
45 } else {
46 Ok(None) }
48 } else {
49 Ok(None) }
51 } else {
52 Err(custom_error(ctx, "Expected expref or string field name"))
53 }
54}
55
56pub fn register_filtered(runtime: &mut Runtime, enabled: &HashSet<&str>) {
58 register_if_enabled(runtime, "unique", enabled, Box::new(UniqueFn::new()));
59 register_if_enabled(runtime, "zip", enabled, Box::new(ZipFn::new()));
60 register_if_enabled(runtime, "chunk", enabled, Box::new(ChunkFn::new()));
61 register_if_enabled(runtime, "take", enabled, Box::new(TakeFn::new()));
62 register_if_enabled(runtime, "drop", enabled, Box::new(DropFn::new()));
63 register_if_enabled(
64 runtime,
65 "flatten_deep",
66 enabled,
67 Box::new(FlattenDeepFn::new()),
68 );
69 register_if_enabled(runtime, "flatten", enabled, Box::new(FlattenFn::new()));
70 register_if_enabled(runtime, "compact", enabled, Box::new(CompactFn::new()));
71 register_if_enabled(runtime, "range", enabled, Box::new(RangeFn::new()));
72 register_if_enabled(runtime, "index_at", enabled, Box::new(IndexAtFn::new()));
73 register_if_enabled(runtime, "includes", enabled, Box::new(IncludesFn::new()));
74 register_if_enabled(runtime, "find_index", enabled, Box::new(FindIndexFn::new()));
75 register_if_enabled(runtime, "first", enabled, Box::new(FirstFn::new()));
76 register_if_enabled(runtime, "last", enabled, Box::new(LastFn::new()));
77 register_if_enabled(runtime, "group_by", enabled, Box::new(GroupByFn::new()));
78 register_if_enabled(runtime, "index_by", enabled, Box::new(IndexByFn::new()));
79 register_if_enabled(runtime, "nth", enabled, Box::new(NthFn::new()));
80 register_if_enabled(
81 runtime,
82 "interleave",
83 enabled,
84 Box::new(InterleaveFn::new()),
85 );
86 register_if_enabled(runtime, "rotate", enabled, Box::new(RotateFn::new()));
87 register_if_enabled(runtime, "partition", enabled, Box::new(PartitionFn::new()));
88 register_if_enabled(
89 runtime,
90 "difference",
91 enabled,
92 Box::new(DifferenceFn::new()),
93 );
94 register_if_enabled(
95 runtime,
96 "intersection",
97 enabled,
98 Box::new(IntersectionFn::new()),
99 );
100 register_if_enabled(runtime, "union", enabled, Box::new(UnionFn::new()));
101 register_if_enabled(
102 runtime,
103 "frequencies",
104 enabled,
105 Box::new(FrequenciesFn::new()),
106 );
107 register_if_enabled(runtime, "mode", enabled, Box::new(ModeFn::new()));
108 register_if_enabled(runtime, "cartesian", enabled, Box::new(CartesianFn::new()));
109 register_if_enabled(runtime, "initial", enabled, Box::new(InitialFn::new()));
110 register_if_enabled(runtime, "butlast", enabled, Box::new(InitialFn::new()));
112 register_if_enabled(runtime, "interpose", enabled, Box::new(InterposeFn::new()));
114 register_if_enabled(runtime, "zipmap", enabled, Box::new(ZipmapFn::new()));
115 register_if_enabled(
116 runtime,
117 "partition_by",
118 enabled,
119 Box::new(PartitionByFn::new()),
120 );
121 register_if_enabled(runtime, "dedupe", enabled, Box::new(DedupeFn::new()));
122 register_if_enabled(runtime, "tail", enabled, Box::new(TailFn::new()));
123 register_if_enabled(runtime, "without", enabled, Box::new(WithoutFn::new()));
124 register_if_enabled(runtime, "xor", enabled, Box::new(XorFn::new()));
125 register_if_enabled(runtime, "fill", enabled, Box::new(FillFn::new()));
126 register_if_enabled(runtime, "pull_at", enabled, Box::new(PullAtFn::new()));
127 register_if_enabled(runtime, "window", enabled, Box::new(WindowFn::new()));
128 register_if_enabled(
129 runtime,
130 "combinations",
131 enabled,
132 Box::new(CombinationsFn::new()),
133 );
134 register_if_enabled(runtime, "transpose", enabled, Box::new(TransposeFn::new()));
135 register_if_enabled(runtime, "pairwise", enabled, Box::new(PairwiseFn::new()));
136 register_if_enabled(
138 runtime,
139 "sliding_window",
140 enabled,
141 Box::new(WindowFn::new()),
142 );
143 register_if_enabled(
145 runtime,
146 "indices_array",
147 enabled,
148 Box::new(IndicesArrayFn::new()),
149 );
150 register_if_enabled(
151 runtime,
152 "inside_array",
153 enabled,
154 Box::new(InsideArrayFn::new()),
155 );
156 register_if_enabled(runtime, "bsearch", enabled, Box::new(BsearchFn::new()));
157 register_if_enabled(
159 runtime,
160 "repeat_array",
161 enabled,
162 Box::new(RepeatArrayFn::new()),
163 );
164 register_if_enabled(runtime, "cycle", enabled, Box::new(CycleFn::new()));
165 register_if_enabled(runtime, "lag", enabled, Box::new(LagFn::new()));
166 register_if_enabled(runtime, "lead", enabled, Box::new(LeadFn::new()));
167}
168
169defn!(UniqueFn, vec![arg!(array)], None);
174
175impl Function for UniqueFn {
176 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
177 self.signature.validate(args, ctx)?;
178
179 let arr = args[0]
180 .as_array()
181 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
182
183 let mut seen = HashSet::new();
184 let mut result = Vec::new();
185
186 for item in arr {
187 let key = serde_json::to_string(item).unwrap_or_default();
188 if seen.insert(key) {
189 result.push(item.clone());
190 }
191 }
192
193 Ok(Value::Array(result))
194 }
195}
196
197defn!(ZipFn, vec![arg!(array), arg!(array)], None);
202
203impl Function for ZipFn {
204 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
205 self.signature.validate(args, ctx)?;
206
207 let arr1 = args[0]
208 .as_array()
209 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
210
211 let arr2 = args[1]
212 .as_array()
213 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
214
215 let result: Vec<Value> = arr1
216 .iter()
217 .zip(arr2.iter())
218 .map(|(a, b)| Value::Array(vec![a.clone(), b.clone()]))
219 .collect();
220
221 Ok(Value::Array(result))
222 }
223}
224
225defn!(ChunkFn, vec![arg!(array), arg!(number)], None);
230
231impl Function for ChunkFn {
232 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
233 self.signature.validate(args, ctx)?;
234
235 let arr = args[0]
236 .as_array()
237 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
238
239 let size = args[1]
240 .as_f64()
241 .map(|n| n as usize)
242 .ok_or_else(|| custom_error(ctx, "Expected positive number for size"))?;
243
244 if size == 0 {
245 return Ok(Value::Array(vec![]));
246 }
247
248 let chunks: Vec<Value> = arr
249 .chunks(size)
250 .map(|chunk| Value::Array(chunk.to_vec()))
251 .collect();
252
253 Ok(Value::Array(chunks))
254 }
255}
256
257defn!(TakeFn, vec![arg!(array), arg!(number)], None);
262
263impl Function for TakeFn {
264 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
265 self.signature.validate(args, ctx)?;
266
267 let arr = args[0]
268 .as_array()
269 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
270
271 let n = args[1]
272 .as_f64()
273 .map(|n| n as usize)
274 .ok_or_else(|| custom_error(ctx, "Expected positive number"))?;
275
276 let result: Vec<Value> = arr.iter().take(n).cloned().collect();
277
278 Ok(Value::Array(result))
279 }
280}
281
282defn!(DropFn, vec![arg!(array), arg!(number)], None);
287
288impl Function for DropFn {
289 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
290 self.signature.validate(args, ctx)?;
291
292 let arr = args[0]
293 .as_array()
294 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
295
296 let n = args[1]
297 .as_f64()
298 .map(|n| n as usize)
299 .ok_or_else(|| custom_error(ctx, "Expected positive number"))?;
300
301 let result: Vec<Value> = arr.iter().skip(n).cloned().collect();
302
303 Ok(Value::Array(result))
304 }
305}
306
307defn!(FlattenDeepFn, vec![arg!(array)], None);
312
313fn flatten_recursive(arr: &[Value]) -> Vec<Value> {
314 let mut result = Vec::new();
315 for item in arr {
316 if let Some(inner) = item.as_array() {
317 result.extend(flatten_recursive(inner));
318 } else {
319 result.push(item.clone());
320 }
321 }
322 result
323}
324
325impl Function for FlattenDeepFn {
326 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
327 self.signature.validate(args, ctx)?;
328
329 let arr = args[0]
330 .as_array()
331 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
332
333 Ok(Value::Array(flatten_recursive(arr)))
334 }
335}
336
337defn!(FlattenFn, vec![arg!(array)], None);
342
343impl Function for FlattenFn {
344 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
345 self.signature.validate(args, ctx)?;
346
347 let arr = args[0]
348 .as_array()
349 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
350
351 let mut result = Vec::new();
352 for item in arr {
353 if let Some(inner) = item.as_array() {
354 result.extend(inner.iter().cloned());
355 } else {
356 result.push(item.clone());
357 }
358 }
359
360 Ok(Value::Array(result))
361 }
362}
363
364defn!(CompactFn, vec![arg!(array)], None);
369
370impl Function for CompactFn {
371 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
372 self.signature.validate(args, ctx)?;
373
374 let arr = args[0]
375 .as_array()
376 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
377
378 let result: Vec<Value> = arr
379 .iter()
380 .filter(|v| !v.is_null() && !matches!(v, Value::Bool(false)))
381 .cloned()
382 .collect();
383
384 Ok(Value::Array(result))
385 }
386}
387
388defn!(
393 RangeFn,
394 vec![arg!(number), arg!(number)],
395 Some(arg!(number))
396);
397
398impl Function for RangeFn {
399 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
400 self.signature.validate(args, ctx)?;
401
402 let start = args[0]
403 .as_f64()
404 .map(|n| n as i64)
405 .ok_or_else(|| custom_error(ctx, "Expected start number"))?;
406
407 let end = args[1]
408 .as_f64()
409 .map(|n| n as i64)
410 .ok_or_else(|| custom_error(ctx, "Expected end number"))?;
411
412 let step = if args.len() > 2 {
413 args[2]
414 .as_f64()
415 .map(|n| n as i64)
416 .ok_or_else(|| custom_error(ctx, "Expected step number"))?
417 } else {
418 1
419 };
420
421 if step == 0 {
422 return Err(custom_error(ctx, "Step cannot be zero"));
423 }
424
425 let mut result = Vec::new();
426 let mut current = start;
427
428 const MAX_RANGE: usize = 10000;
429
430 if step > 0 {
431 while current < end && result.len() < MAX_RANGE {
432 result.push(Value::Number(Number::from(current)));
433 current += step;
434 }
435 } else {
436 while current > end && result.len() < MAX_RANGE {
437 result.push(Value::Number(Number::from(current)));
438 current += step;
439 }
440 }
441
442 Ok(Value::Array(result))
443 }
444}
445
446defn!(IndexAtFn, vec![arg!(array), arg!(number)], None);
451
452impl Function for IndexAtFn {
453 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
454 self.signature.validate(args, ctx)?;
455
456 let arr = args[0]
457 .as_array()
458 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
459
460 let index = args[1]
461 .as_f64()
462 .map(|n| n as i64)
463 .ok_or_else(|| custom_error(ctx, "Expected number for index"))?;
464
465 let len = arr.len() as i64;
466 let actual_index = if index < 0 {
467 (len + index) as usize
468 } else {
469 index as usize
470 };
471
472 if actual_index < arr.len() {
473 Ok(arr[actual_index].clone())
474 } else {
475 Ok(Value::Null)
476 }
477 }
478}
479
480defn!(IncludesFn, vec![arg!(array), arg!(any)], None);
485
486impl Function for IncludesFn {
487 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
488 self.signature.validate(args, ctx)?;
489
490 let arr = args[0]
491 .as_array()
492 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
493
494 let search_key = serde_json::to_string(&args[1]).unwrap_or_default();
495
496 let found = arr.iter().any(|item| {
497 let item_key = serde_json::to_string(item).unwrap_or_default();
498 item_key == search_key
499 });
500
501 Ok(Value::Bool(found))
502 }
503}
504
505defn!(FindIndexFn, vec![arg!(array), arg!(any)], None);
510
511impl Function for FindIndexFn {
512 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
513 self.signature.validate(args, ctx)?;
514
515 let arr = args[0]
516 .as_array()
517 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
518
519 let search_key = serde_json::to_string(&args[1]).unwrap_or_default();
520
521 let index = arr
522 .iter()
523 .position(|item| {
524 let item_key = serde_json::to_string(item).unwrap_or_default();
525 item_key == search_key
526 })
527 .map(|i| i as i64)
528 .unwrap_or(-1);
529
530 Ok(Value::Number(Number::from(index)))
531 }
532}
533
534defn!(FirstFn, vec![arg!(array)], None);
539
540impl Function for FirstFn {
541 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
542 self.signature.validate(args, ctx)?;
543
544 let arr = args[0]
545 .as_array()
546 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
547
548 Ok(arr.first().cloned().unwrap_or(Value::Null))
549 }
550}
551
552defn!(LastFn, vec![arg!(array)], None);
557
558impl Function for LastFn {
559 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
560 self.signature.validate(args, ctx)?;
561
562 let arr = args[0]
563 .as_array()
564 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
565
566 Ok(arr.last().cloned().unwrap_or(Value::Null))
567 }
568}
569
570defn!(GroupByFn, vec![arg!(array), arg!(expref | string)], None);
575
576impl Function for GroupByFn {
577 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
578 self.signature.validate(args, ctx)?;
579
580 let arr = args[0]
581 .as_array()
582 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
583
584 let mut group_keys: Vec<String> = Vec::new();
585 let mut group_map: std::collections::HashMap<String, Vec<Value>> =
586 std::collections::HashMap::new();
587
588 for item in arr {
589 let key = match extract_key(item, &args[1], ctx)? {
590 Some(k) => k,
591 None => "null".to_string(),
592 };
593 if !group_map.contains_key(&key) {
594 group_keys.push(key.clone());
595 }
596 group_map.entry(key).or_default().push(item.clone());
597 }
598
599 let mut result = serde_json::Map::new();
600 for key in group_keys {
601 if let Some(items) = group_map.remove(&key) {
602 result.insert(key, Value::Array(items));
603 }
604 }
605
606 Ok(Value::Object(result))
607 }
608}
609
610defn!(IndexByFn, vec![arg!(array), arg!(expref | string)], None);
615
616impl Function for IndexByFn {
617 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
618 self.signature.validate(args, ctx)?;
619
620 let arr = args[0]
621 .as_array()
622 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
623
624 let mut result = serde_json::Map::new();
625
626 for item in arr {
627 let key = match extract_key(item, &args[1], ctx)? {
628 Some(k) => k,
629 None => continue, };
631 result.insert(key, item.clone());
633 }
634
635 Ok(Value::Object(result))
636 }
637}
638
639defn!(NthFn, vec![arg!(array), arg!(number)], None);
644
645impl Function for NthFn {
646 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
647 self.signature.validate(args, ctx)?;
648
649 let arr = args[0]
650 .as_array()
651 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
652
653 let n = args[1]
654 .as_f64()
655 .ok_or_else(|| custom_error(ctx, "Expected number argument"))? as usize;
656
657 if n == 0 {
658 return Ok(Value::Null);
659 }
660
661 let result: Vec<Value> = arr.iter().step_by(n).cloned().collect();
662 Ok(Value::Array(result))
663 }
664}
665
666defn!(InterleaveFn, vec![arg!(array), arg!(array)], None);
671
672impl Function for InterleaveFn {
673 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
674 self.signature.validate(args, ctx)?;
675
676 let arr1 = args[0]
677 .as_array()
678 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
679
680 let arr2 = args[1]
681 .as_array()
682 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
683
684 let mut result = Vec::with_capacity(arr1.len() + arr2.len());
685 let mut iter1 = arr1.iter();
686 let mut iter2 = arr2.iter();
687
688 loop {
689 match (iter1.next(), iter2.next()) {
690 (Some(a), Some(b)) => {
691 result.push(a.clone());
692 result.push(b.clone());
693 }
694 (Some(a), None) => {
695 result.push(a.clone());
696 result.extend(iter1.cloned());
697 break;
698 }
699 (None, Some(b)) => {
700 result.push(b.clone());
701 result.extend(iter2.cloned());
702 break;
703 }
704 (None, None) => break,
705 }
706 }
707
708 Ok(Value::Array(result))
709 }
710}
711
712defn!(RotateFn, vec![arg!(array), arg!(number)], None);
717
718impl Function for RotateFn {
719 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
720 self.signature.validate(args, ctx)?;
721
722 let arr = args[0]
723 .as_array()
724 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
725
726 if arr.is_empty() {
727 return Ok(Value::Array(vec![]));
728 }
729
730 let n = args[1]
731 .as_f64()
732 .ok_or_else(|| custom_error(ctx, "Expected number argument"))? as i64;
733
734 let len = arr.len() as i64;
735 let rotation = ((n % len) + len) % len;
736 let rotation = rotation as usize;
737
738 let mut result = Vec::with_capacity(arr.len());
739 result.extend(arr[rotation..].iter().cloned());
740 result.extend(arr[..rotation].iter().cloned());
741
742 Ok(Value::Array(result))
743 }
744}
745
746defn!(PartitionFn, vec![arg!(array), arg!(number)], None);
751
752impl Function for PartitionFn {
753 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
754 self.signature.validate(args, ctx)?;
755
756 let arr = args[0]
757 .as_array()
758 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
759
760 let n = args[1]
761 .as_f64()
762 .ok_or_else(|| custom_error(ctx, "Expected number argument"))? as usize;
763
764 if n == 0 {
765 return Ok(Value::Null);
766 }
767
768 let len = arr.len();
769 let base_size = len / n;
770 let remainder = len % n;
771
772 let mut result = Vec::with_capacity(n);
773 let mut start = 0;
774
775 for i in 0..n {
776 let size = base_size + if i < remainder { 1 } else { 0 };
777 if size > 0 {
778 result.push(Value::Array(arr[start..start + size].to_vec()));
779 } else {
780 result.push(Value::Array(vec![]));
781 }
782 start += size;
783 }
784
785 Ok(Value::Array(result))
786 }
787}
788
789defn!(DifferenceFn, vec![arg!(array), arg!(array)], None);
794
795impl Function for DifferenceFn {
796 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
797 self.signature.validate(args, ctx)?;
798
799 let arr1 = args[0]
800 .as_array()
801 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
802
803 let arr2 = args[1]
804 .as_array()
805 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
806
807 let set2: HashSet<String> = arr2
808 .iter()
809 .map(|v| serde_json::to_string(v).unwrap_or_default())
810 .collect();
811
812 let result: Vec<Value> = arr1
813 .iter()
814 .filter(|v| {
815 let key = serde_json::to_string(*v).unwrap_or_default();
816 !set2.contains(&key)
817 })
818 .cloned()
819 .collect();
820
821 Ok(Value::Array(result))
822 }
823}
824
825defn!(IntersectionFn, vec![arg!(array), arg!(array)], None);
830
831impl Function for IntersectionFn {
832 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
833 self.signature.validate(args, ctx)?;
834
835 let arr1 = args[0]
836 .as_array()
837 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
838
839 let arr2 = args[1]
840 .as_array()
841 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
842
843 let set2: HashSet<String> = arr2
844 .iter()
845 .map(|v| serde_json::to_string(v).unwrap_or_default())
846 .collect();
847
848 let mut seen: HashSet<String> = HashSet::new();
849 let result: Vec<Value> = arr1
850 .iter()
851 .filter(|v| {
852 let key = serde_json::to_string(*v).unwrap_or_default();
853 set2.contains(&key) && seen.insert(key)
854 })
855 .cloned()
856 .collect();
857
858 Ok(Value::Array(result))
859 }
860}
861
862defn!(UnionFn, vec![arg!(array), arg!(array)], None);
867
868impl Function for UnionFn {
869 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
870 self.signature.validate(args, ctx)?;
871
872 let arr1 = args[0]
873 .as_array()
874 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
875
876 let arr2 = args[1]
877 .as_array()
878 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
879
880 let mut seen: HashSet<String> = HashSet::new();
881 let mut result: Vec<Value> = Vec::new();
882
883 for item in arr1.iter().chain(arr2.iter()) {
884 let key = serde_json::to_string(item).unwrap_or_default();
885 if seen.insert(key) {
886 result.push(item.clone());
887 }
888 }
889
890 Ok(Value::Array(result))
891 }
892}
893
894defn!(FrequenciesFn, vec![arg!(array)], None);
899
900impl Function for FrequenciesFn {
901 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
902 self.signature.validate(args, ctx)?;
903
904 let arr = args[0]
905 .as_array()
906 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
907
908 let mut counts: std::collections::HashMap<String, i64> = std::collections::HashMap::new();
909
910 for item in arr {
911 let key = match item {
912 Value::String(s) => s.clone(),
913 Value::Number(n) => n.to_string(),
914 Value::Bool(b) => b.to_string(),
915 Value::Null => "null".to_string(),
916 _ => serde_json::to_string(item).unwrap_or_else(|_| "null".to_string()),
917 };
918 *counts.entry(key).or_insert(0) += 1;
919 }
920
921 let mut result = serde_json::Map::new();
922 let sorted: std::collections::BTreeMap<String, i64> = counts.into_iter().collect();
924 for (k, v) in sorted {
925 result.insert(k, Value::Number(Number::from(v)));
926 }
927
928 Ok(Value::Object(result))
929 }
930}
931
932defn!(ModeFn, vec![arg!(array)], None);
937
938impl Function for ModeFn {
939 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
940 self.signature.validate(args, ctx)?;
941
942 let arr = args[0]
943 .as_array()
944 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
945
946 if arr.is_empty() {
947 return Ok(Value::Null);
948 }
949
950 let mut counts: std::collections::HashMap<String, (i64, Value)> =
951 std::collections::HashMap::new();
952
953 for item in arr {
954 let key = serde_json::to_string(item).unwrap_or_default();
955 counts
956 .entry(key)
957 .and_modify(|(count, _)| *count += 1)
958 .or_insert((1, item.clone()));
959 }
960
961 let (_, (_, mode_value)) = counts
962 .into_iter()
963 .max_by_key(|(_, (count, _))| *count)
964 .unwrap();
965
966 Ok(mode_value)
967 }
968}
969
970defn!(CartesianFn, vec![arg!(array)], Some(arg!(array)));
976
977impl Function for CartesianFn {
978 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
979 self.signature.validate(args, ctx)?;
980
981 let first = args[0]
982 .as_array()
983 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
984
985 if args.len() == 2 {
990 let arr2 = args[1]
992 .as_array()
993 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
994
995 let mut result = Vec::with_capacity(first.len() * arr2.len());
996 for a in first {
997 for b in arr2 {
998 result.push(Value::Array(vec![a.clone(), b.clone()]));
999 }
1000 }
1001 Ok(Value::Array(result))
1002 } else {
1003 let arrays: Vec<&Vec<Value>> =
1006 first.iter().filter_map(|item| item.as_array()).collect();
1007
1008 if arrays.len() != first.len() || arrays.is_empty() {
1009 return Ok(Value::Array(vec![]));
1011 }
1012
1013 let result = cartesian_product_n(&arrays);
1015 Ok(Value::Array(result))
1016 }
1017 }
1018}
1019
1020fn cartesian_product_n(arrays: &[&Vec<Value>]) -> Vec<Value> {
1022 if arrays.is_empty() {
1023 return vec![];
1024 }
1025
1026 if arrays.len() == 1 {
1027 return arrays[0]
1029 .iter()
1030 .map(|item| Value::Array(vec![item.clone()]))
1031 .collect();
1032 }
1033
1034 let total_size: usize = arrays.iter().map(|a| a.len()).product();
1036 if total_size == 0 {
1037 return vec![];
1038 }
1039
1040 let mut result = Vec::with_capacity(total_size);
1041
1042 let mut indices = vec![0usize; arrays.len()];
1044
1045 loop {
1046 let combo: Vec<Value> = indices
1048 .iter()
1049 .enumerate()
1050 .map(|(arr_idx, &elem_idx)| arrays[arr_idx][elem_idx].clone())
1051 .collect();
1052 result.push(Value::Array(combo));
1053
1054 let mut carry = true;
1056 for i in (0..arrays.len()).rev() {
1057 if carry {
1058 indices[i] += 1;
1059 if indices[i] >= arrays[i].len() {
1060 indices[i] = 0;
1061 } else {
1062 carry = false;
1063 }
1064 }
1065 }
1066
1067 if carry {
1069 break;
1070 }
1071 }
1072
1073 result
1074}
1075
1076defn!(InitialFn, vec![arg!(array)], None);
1081
1082impl Function for InitialFn {
1083 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1084 self.signature.validate(args, ctx)?;
1085
1086 let arr = args[0]
1087 .as_array()
1088 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1089
1090 if arr.is_empty() {
1091 return Ok(Value::Array(vec![]));
1092 }
1093
1094 let result: Vec<Value> = arr[..arr.len() - 1].to_vec();
1095 Ok(Value::Array(result))
1096 }
1097}
1098
1099defn!(InterposeFn, vec![arg!(array), arg!(any)], None);
1104
1105impl Function for InterposeFn {
1106 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1107 self.signature.validate(args, ctx)?;
1108
1109 let arr = args[0]
1110 .as_array()
1111 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1112
1113 let separator = args[1].clone();
1114
1115 if arr.is_empty() {
1116 return Ok(Value::Array(vec![]));
1117 }
1118
1119 if arr.len() == 1 {
1120 return Ok(Value::Array(arr.clone()));
1121 }
1122
1123 let mut result = Vec::with_capacity(arr.len() * 2 - 1);
1124 for (i, item) in arr.iter().enumerate() {
1125 if i > 0 {
1126 result.push(separator.clone());
1127 }
1128 result.push(item.clone());
1129 }
1130
1131 Ok(Value::Array(result))
1132 }
1133}
1134
1135defn!(ZipmapFn, vec![arg!(array), arg!(array)], None);
1140
1141impl Function for ZipmapFn {
1142 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1143 self.signature.validate(args, ctx)?;
1144
1145 let keys = args[0]
1146 .as_array()
1147 .ok_or_else(|| custom_error(ctx, "Expected array argument for keys"))?;
1148
1149 let values = args[1]
1150 .as_array()
1151 .ok_or_else(|| custom_error(ctx, "Expected array argument for values"))?;
1152
1153 let len = keys.len().min(values.len());
1154 let mut result = serde_json::Map::new();
1155
1156 for i in 0..len {
1157 let key = keys[i]
1158 .as_str()
1159 .ok_or_else(|| custom_error(ctx, "Keys must be strings"))?;
1160 result.insert(key.to_string(), values[i].clone());
1161 }
1162
1163 Ok(Value::Object(result))
1164 }
1165}
1166
1167defn!(
1172 PartitionByFn,
1173 vec![arg!(array), arg!(expref | string)],
1174 None
1175);
1176
1177impl Function for PartitionByFn {
1178 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1179 self.signature.validate(args, ctx)?;
1180
1181 let arr = args[0]
1182 .as_array()
1183 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1184
1185 if arr.is_empty() {
1186 return Ok(Value::Array(vec![]));
1187 }
1188
1189 let is_expref = get_expref_ast(&args[1], ctx).is_some();
1190
1191 let mut result: Vec<Value> = Vec::new();
1192 let mut current_partition: Vec<Value> = Vec::new();
1193 let mut last_key: Option<String> = None;
1194
1195 for item in arr {
1196 let key = if is_expref {
1197 match extract_key(item, &args[1], ctx)? {
1199 Some(k) => k,
1200 None => "null".to_string(),
1201 }
1202 } else if let Some(field_name) = args[1].as_str() {
1203 if let Some(obj) = item.as_object() {
1205 if let Some(field_value) = obj.get(field_name) {
1206 serde_json::to_string(field_value).unwrap_or_default()
1207 } else {
1208 "null".to_string()
1209 }
1210 } else {
1211 serde_json::to_string(item).unwrap_or_default()
1212 }
1213 } else {
1214 return Err(custom_error(ctx, "Expected expref or string field name"));
1215 };
1216
1217 match &last_key {
1218 Some(prev_key) if *prev_key == key => {
1219 current_partition.push(item.clone());
1220 }
1221 _ => {
1222 if !current_partition.is_empty() {
1223 result.push(Value::Array(current_partition));
1224 }
1225 current_partition = vec![item.clone()];
1226 last_key = Some(key);
1227 }
1228 }
1229 }
1230
1231 if !current_partition.is_empty() {
1233 result.push(Value::Array(current_partition));
1234 }
1235
1236 Ok(Value::Array(result))
1237 }
1238}
1239
1240defn!(DedupeFn, vec![arg!(array)], None);
1245
1246impl Function for DedupeFn {
1247 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1248 self.signature.validate(args, ctx)?;
1249
1250 let arr = args[0]
1251 .as_array()
1252 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1253
1254 if arr.is_empty() {
1255 return Ok(Value::Array(vec![]));
1256 }
1257
1258 let mut result: Vec<Value> = Vec::with_capacity(arr.len());
1259 let mut last_key: Option<String> = None;
1260
1261 for item in arr {
1262 let key = serde_json::to_string(item).unwrap_or_default();
1263 match &last_key {
1264 Some(prev_key) if *prev_key == key => {
1265 }
1267 _ => {
1268 result.push(item.clone());
1269 last_key = Some(key);
1270 }
1271 }
1272 }
1273
1274 Ok(Value::Array(result))
1275 }
1276}
1277
1278defn!(TailFn, vec![arg!(array)], None);
1283
1284impl Function for TailFn {
1285 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1286 self.signature.validate(args, ctx)?;
1287
1288 let arr = args[0]
1289 .as_array()
1290 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1291
1292 if arr.is_empty() {
1293 return Ok(Value::Array(vec![]));
1294 }
1295
1296 let result: Vec<Value> = arr[1..].to_vec();
1297 Ok(Value::Array(result))
1298 }
1299}
1300
1301defn!(WithoutFn, vec![arg!(array), arg!(array)], None);
1306
1307impl Function for WithoutFn {
1308 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1309 self.signature.validate(args, ctx)?;
1310
1311 let arr = args[0]
1312 .as_array()
1313 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1314
1315 let exclude = args[1]
1316 .as_array()
1317 .ok_or_else(|| custom_error(ctx, "Expected array argument for values to exclude"))?;
1318
1319 let exclude_set: HashSet<String> = exclude
1321 .iter()
1322 .map(|v| serde_json::to_string(v).unwrap_or_default())
1323 .collect();
1324
1325 let result: Vec<Value> = arr
1326 .iter()
1327 .filter(|item| {
1328 let key = serde_json::to_string(*item).unwrap_or_default();
1329 !exclude_set.contains(&key)
1330 })
1331 .cloned()
1332 .collect();
1333
1334 Ok(Value::Array(result))
1335 }
1336}
1337
1338defn!(XorFn, vec![arg!(array), arg!(array)], None);
1343
1344impl Function for XorFn {
1345 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1346 self.signature.validate(args, ctx)?;
1347
1348 let arr1 = args[0]
1349 .as_array()
1350 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1351
1352 let arr2 = args[1]
1353 .as_array()
1354 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1355
1356 let set1: HashSet<String> = arr1
1358 .iter()
1359 .map(|v| serde_json::to_string(v).unwrap_or_default())
1360 .collect();
1361
1362 let set2: HashSet<String> = arr2
1363 .iter()
1364 .map(|v| serde_json::to_string(v).unwrap_or_default())
1365 .collect();
1366
1367 let mut result = Vec::new();
1368
1369 for item in arr1 {
1371 let key = serde_json::to_string(item).unwrap_or_default();
1372 if !set2.contains(&key) {
1373 result.push(item.clone());
1374 }
1375 }
1376
1377 for item in arr2 {
1379 let key = serde_json::to_string(item).unwrap_or_default();
1380 if !set1.contains(&key) {
1381 result.push(item.clone());
1382 }
1383 }
1384
1385 Ok(Value::Array(result))
1386 }
1387}
1388
1389defn!(
1394 WindowFn,
1395 vec![arg!(array), arg!(number)],
1396 Some(arg!(number))
1397);
1398
1399impl Function for WindowFn {
1400 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1401 self.signature.validate(args, ctx)?;
1402
1403 let arr = args[0]
1404 .as_array()
1405 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1406
1407 let size = args[1]
1408 .as_f64()
1409 .ok_or_else(|| custom_error(ctx, "Expected number for window size"))?
1410 as usize;
1411
1412 if size == 0 {
1413 return Ok(Value::Array(vec![]));
1414 }
1415
1416 let step = if args.len() > 2 {
1418 args[2]
1419 .as_f64()
1420 .ok_or_else(|| custom_error(ctx, "Expected number for step"))? as usize
1421 } else {
1422 1
1423 };
1424
1425 if step == 0 {
1426 return Err(custom_error(ctx, "Step cannot be zero"));
1427 }
1428
1429 let len = arr.len();
1430 if len < size {
1431 return Ok(Value::Array(vec![]));
1432 }
1433
1434 let mut result = Vec::new();
1435 let mut i = 0;
1436
1437 while i + size <= len {
1438 let window: Vec<Value> = arr[i..i + size].to_vec();
1439 result.push(Value::Array(window));
1440 i += step;
1441 }
1442
1443 Ok(Value::Array(result))
1444 }
1445}
1446
1447defn!(CombinationsFn, vec![arg!(array), arg!(number)], None);
1452
1453fn generate_combinations(arr: &[Value], k: usize) -> Vec<Vec<Value>> {
1454 if k == 0 {
1455 return vec![vec![]];
1456 }
1457 if arr.len() < k {
1458 return vec![];
1459 }
1460
1461 let mut result = Vec::new();
1462
1463 let first = arr[0].clone();
1465 let rest = &arr[1..];
1466 for mut combo in generate_combinations(rest, k - 1) {
1467 let mut new_combo = vec![first.clone()];
1468 new_combo.append(&mut combo);
1469 result.push(new_combo);
1470 }
1471
1472 result.extend(generate_combinations(rest, k));
1474
1475 result
1476}
1477
1478impl Function for CombinationsFn {
1479 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1480 self.signature.validate(args, ctx)?;
1481
1482 let arr = args[0]
1483 .as_array()
1484 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1485
1486 let k = args[1]
1487 .as_f64()
1488 .ok_or_else(|| custom_error(ctx, "Expected number for k"))? as usize;
1489
1490 const MAX_COMBINATIONS: usize = 10000;
1492
1493 let n = arr.len();
1495 if n > 20 && k > 3 && k < n - 3 {
1496 return Err(custom_error(ctx, "Combination size too large"));
1497 }
1498
1499 let combinations = generate_combinations(arr, k);
1500
1501 if combinations.len() > MAX_COMBINATIONS {
1502 return Err(custom_error(ctx, "Too many combinations generated"));
1503 }
1504
1505 let result: Vec<Value> = combinations.into_iter().map(Value::Array).collect();
1506
1507 Ok(Value::Array(result))
1508 }
1509}
1510
1511defn!(FillFn, vec![arg!(array), arg!(any)], Some(arg!(number)));
1516
1517impl Function for FillFn {
1518 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1519 self.signature.validate(args, ctx)?;
1520
1521 let arr = args[0]
1522 .as_array()
1523 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1524
1525 let fill_value = args[1].clone();
1526
1527 let len = arr.len();
1528 if len == 0 {
1529 return Ok(Value::Array(vec![]));
1530 }
1531
1532 let start = if args.len() > 2 {
1534 let s = args[2]
1535 .as_f64()
1536 .ok_or_else(|| custom_error(ctx, "Expected number for start index"))?
1537 as i64;
1538 if s < 0 {
1540 (len as i64 + s).max(0) as usize
1541 } else {
1542 (s as usize).min(len)
1543 }
1544 } else {
1545 0
1546 };
1547
1548 let end = if args.len() > 3 {
1549 let e = args[3]
1550 .as_f64()
1551 .ok_or_else(|| custom_error(ctx, "Expected number for end index"))?
1552 as i64;
1553 if e < 0 {
1555 (len as i64 + e).max(0) as usize
1556 } else {
1557 (e as usize).min(len)
1558 }
1559 } else {
1560 len
1561 };
1562
1563 let mut result: Vec<Value> = arr.clone();
1564
1565 for item in result.iter_mut().take(end.min(len)).skip(start) {
1566 *item = fill_value.clone();
1567 }
1568
1569 Ok(Value::Array(result))
1570 }
1571}
1572
1573defn!(PullAtFn, vec![arg!(array), arg!(array)], None);
1578
1579impl Function for PullAtFn {
1580 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1581 self.signature.validate(args, ctx)?;
1582
1583 let arr = args[0]
1584 .as_array()
1585 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1586
1587 let indices = args[1]
1588 .as_array()
1589 .ok_or_else(|| custom_error(ctx, "Expected array of indices"))?;
1590
1591 let len = arr.len();
1592 let mut result = Vec::new();
1593
1594 for idx_var in indices {
1595 let idx = idx_var
1596 .as_f64()
1597 .ok_or_else(|| custom_error(ctx, "Expected number in indices array"))?
1598 as i64;
1599
1600 let actual_idx = if idx < 0 {
1602 (len as i64 + idx).max(0) as usize
1603 } else {
1604 idx as usize
1605 };
1606
1607 if actual_idx < len {
1608 result.push(arr[actual_idx].clone());
1609 }
1610 }
1611
1612 Ok(Value::Array(result))
1613 }
1614}
1615
1616defn!(TransposeFn, vec![arg!(array)], None);
1621
1622impl Function for TransposeFn {
1623 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1624 self.signature.validate(args, ctx)?;
1625
1626 let arr = args[0]
1627 .as_array()
1628 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1629
1630 if arr.is_empty() {
1631 return Ok(Value::Array(vec![]));
1632 }
1633
1634 let mut inner_arrays: Vec<&Vec<Value>> = Vec::new();
1636 let mut min_len = usize::MAX;
1637
1638 for item in arr {
1639 if let Some(inner) = item.as_array() {
1640 min_len = min_len.min(inner.len());
1641 inner_arrays.push(inner);
1642 } else {
1643 return Ok(Value::Array(vec![]));
1645 }
1646 }
1647
1648 if inner_arrays.is_empty() || min_len == 0 {
1649 return Ok(Value::Array(vec![]));
1650 }
1651
1652 let mut result = Vec::with_capacity(min_len);
1654 for i in 0..min_len {
1655 let mut row = Vec::with_capacity(inner_arrays.len());
1656 for inner in &inner_arrays {
1657 row.push(inner[i].clone());
1658 }
1659 result.push(Value::Array(row));
1660 }
1661
1662 Ok(Value::Array(result))
1663 }
1664}
1665
1666defn!(PairwiseFn, vec![arg!(array)], None);
1671
1672impl Function for PairwiseFn {
1673 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1674 self.signature.validate(args, ctx)?;
1675
1676 let arr = args[0]
1677 .as_array()
1678 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1679
1680 if arr.len() < 2 {
1681 return Ok(Value::Array(vec![]));
1682 }
1683
1684 let mut result = Vec::with_capacity(arr.len() - 1);
1685 for i in 0..arr.len() - 1 {
1686 let pair = vec![arr[i].clone(), arr[i + 1].clone()];
1687 result.push(Value::Array(pair));
1688 }
1689
1690 Ok(Value::Array(result))
1691 }
1692}
1693
1694defn!(IndicesArrayFn, vec![arg!(array), arg!(any)], None);
1699
1700impl Function for IndicesArrayFn {
1701 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1702 self.signature.validate(args, ctx)?;
1703
1704 let arr = args[0]
1705 .as_array()
1706 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1707
1708 let search_key = serde_json::to_string(&args[1]).unwrap_or_default();
1709
1710 let mut indices: Vec<Value> = Vec::new();
1711 for (i, item) in arr.iter().enumerate() {
1712 let item_key = serde_json::to_string(item).unwrap_or_default();
1713 if item_key == search_key {
1714 indices.push(Value::Number(Number::from(i as i64)));
1715 }
1716 }
1717
1718 Ok(Value::Array(indices))
1719 }
1720}
1721
1722defn!(InsideArrayFn, vec![arg!(array), arg!(array)], None);
1727
1728impl Function for InsideArrayFn {
1729 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1730 self.signature.validate(args, ctx)?;
1731
1732 let needle = args[0]
1733 .as_array()
1734 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1735
1736 let haystack = args[1]
1737 .as_array()
1738 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1739
1740 let haystack_set: HashSet<String> = haystack
1742 .iter()
1743 .map(|item| serde_json::to_string(item).unwrap_or_default())
1744 .collect();
1745
1746 let result = needle.iter().all(|item| {
1748 let item_key = serde_json::to_string(item).unwrap_or_default();
1749 haystack_set.contains(&item_key)
1750 });
1751
1752 Ok(Value::Bool(result))
1753 }
1754}
1755
1756defn!(BsearchFn, vec![arg!(array), arg!(any)], None);
1761
1762impl Function for BsearchFn {
1763 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1764 self.signature.validate(args, ctx)?;
1765
1766 let arr = args[0]
1767 .as_array()
1768 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1769
1770 let target = &args[1];
1771
1772 if arr.is_empty() {
1773 return Ok(Value::Number(Number::from(-1)));
1774 }
1775
1776 fn compare_values(a: &Value, b: &Value) -> std::cmp::Ordering {
1779 match (a, b) {
1780 (Value::Number(n1), Value::Number(n2)) => {
1782 let f1 = n1.as_f64().unwrap_or(0.0);
1783 let f2 = n2.as_f64().unwrap_or(0.0);
1784 f1.partial_cmp(&f2).unwrap_or(std::cmp::Ordering::Equal)
1785 }
1786 (Value::String(s1), Value::String(s2)) => s1.cmp(s2),
1788 (Value::Bool(b1), Value::Bool(b2)) => b1.cmp(b2),
1790 _ => {
1792 let s1 = serde_json::to_string(a).unwrap_or_default();
1793 let s2 = serde_json::to_string(b).unwrap_or_default();
1794 s1.cmp(&s2)
1795 }
1796 }
1797 }
1798
1799 let mut left = 0i64;
1800 let mut right = arr.len() as i64 - 1;
1801
1802 while left <= right {
1803 let mid = left + (right - left) / 2;
1804
1805 match compare_values(&arr[mid as usize], target) {
1806 std::cmp::Ordering::Equal => {
1807 return Ok(Value::Number(Number::from(mid)));
1808 }
1809 std::cmp::Ordering::Less => {
1810 left = mid + 1;
1811 }
1812 std::cmp::Ordering::Greater => {
1813 right = mid - 1;
1814 }
1815 }
1816 }
1817
1818 let result = -(left) - 1;
1821 Ok(Value::Number(Number::from(result)))
1822 }
1823}
1824
1825defn!(RepeatArrayFn, vec![arg!(any), arg!(number)], None);
1830
1831impl Function for RepeatArrayFn {
1832 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1833 self.signature.validate(args, ctx)?;
1834
1835 let value = &args[0];
1836 let n = args[1]
1837 .as_f64()
1838 .ok_or_else(|| custom_error(ctx, "Expected number for count argument"))?
1839 as i64;
1840
1841 if n < 0 {
1842 return Err(custom_error(ctx, "Count must be non-negative"));
1843 }
1844
1845 let result: Vec<Value> = (0..n).map(|_| value.clone()).collect();
1846 Ok(Value::Array(result))
1847 }
1848}
1849
1850defn!(CycleFn, vec![arg!(array), arg!(number)], None);
1855
1856impl Function for CycleFn {
1857 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1858 self.signature.validate(args, ctx)?;
1859
1860 let arr = args[0]
1861 .as_array()
1862 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1863
1864 let n = args[1]
1865 .as_f64()
1866 .ok_or_else(|| custom_error(ctx, "Expected number for count argument"))?
1867 as i64;
1868
1869 if n < 0 {
1870 return Err(custom_error(ctx, "Count must be non-negative"));
1871 }
1872
1873 if arr.is_empty() || n == 0 {
1874 return Ok(Value::Array(vec![]));
1875 }
1876
1877 let mut result: Vec<Value> = Vec::with_capacity(arr.len() * n as usize);
1878 for _ in 0..n {
1879 result.extend(arr.iter().cloned());
1880 }
1881 Ok(Value::Array(result))
1882 }
1883}
1884
1885defn!(LagFn, vec![arg!(array), arg!(number)], None);
1890
1891impl Function for LagFn {
1892 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1893 self.signature.validate(args, ctx)?;
1894 let arr = args[0].as_array().unwrap();
1895 let n = args[1].as_f64().unwrap() as usize;
1896 let len = arr.len();
1897 let mut result = Vec::with_capacity(len);
1898 for _ in 0..n.min(len) {
1899 result.push(Value::Null);
1900 }
1901 if n < len {
1902 result.extend_from_slice(&arr[..len - n]);
1903 }
1904 Ok(Value::Array(result))
1905 }
1906}
1907
1908defn!(LeadFn, vec![arg!(array), arg!(number)], None);
1913
1914impl Function for LeadFn {
1915 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1916 self.signature.validate(args, ctx)?;
1917 let arr = args[0].as_array().unwrap();
1918 let n = args[1].as_f64().unwrap() as usize;
1919 let len = arr.len();
1920 let mut result = Vec::with_capacity(len);
1921 if n < len {
1922 result.extend_from_slice(&arr[n..]);
1923 }
1924 let remaining = len.saturating_sub(result.len());
1925 for _ in 0..remaining {
1926 result.push(Value::Null);
1927 }
1928 Ok(Value::Array(result))
1929 }
1930}
1931
1932#[cfg(test)]
1933mod tests {
1934 use crate::Runtime;
1935 use serde_json::json;
1936
1937 fn setup_runtime() -> Runtime {
1938 Runtime::builder()
1939 .with_standard()
1940 .with_all_extensions()
1941 .build()
1942 }
1943
1944 #[test]
1945 fn test_unique() {
1946 let runtime = setup_runtime();
1947 let expr = runtime.compile("unique(@)").unwrap();
1948 let data = json!([1, 2, 1]);
1949 let result = expr.search(&data).unwrap();
1950 let arr = result.as_array().unwrap();
1951 assert_eq!(arr.len(), 2);
1952 }
1953
1954 #[test]
1955 fn test_first() {
1956 let runtime = setup_runtime();
1957 let expr = runtime.compile("first(@)").unwrap();
1958 let data = json!([1, 2]);
1959 let result = expr.search(&data).unwrap();
1960 assert_eq!(result.as_f64().unwrap() as i64, 1);
1961 }
1962
1963 #[test]
1964 fn test_last() {
1965 let runtime = setup_runtime();
1966 let expr = runtime.compile("last(@)").unwrap();
1967 let data = json!([1, 2]);
1968 let result = expr.search(&data).unwrap();
1969 assert_eq!(result.as_f64().unwrap() as i64, 2);
1970 }
1971
1972 #[test]
1973 fn test_range() {
1974 let runtime = setup_runtime();
1975 let expr = runtime.compile("range(`0`, `5`)").unwrap();
1976 let data = json!(null);
1977 let result = expr.search(&data).unwrap();
1978 let arr = result.as_array().unwrap();
1979 assert_eq!(arr.len(), 5);
1980 }
1981
1982 #[test]
1983 fn test_butlast() {
1984 let runtime = setup_runtime();
1986 let expr = runtime.compile("butlast(@)").unwrap();
1987 let data = json!([1, 2, 3]);
1988 let result = expr.search(&data).unwrap();
1989 let arr = result.as_array().unwrap();
1990 assert_eq!(arr.len(), 2);
1991 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
1992 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
1993 }
1994
1995 #[test]
1996 fn test_interpose() {
1997 let runtime = setup_runtime();
1998 let expr = runtime.compile("interpose(@, `0`)").unwrap();
1999 let data = json!([1, 2, 3]);
2000 let result = expr.search(&data).unwrap();
2001 let arr = result.as_array().unwrap();
2002 assert_eq!(arr.len(), 5);
2003 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2004 assert_eq!(arr[1].as_f64().unwrap() as i64, 0);
2005 assert_eq!(arr[2].as_f64().unwrap() as i64, 2);
2006 assert_eq!(arr[3].as_f64().unwrap() as i64, 0);
2007 assert_eq!(arr[4].as_f64().unwrap() as i64, 3);
2008 }
2009
2010 #[test]
2011 fn test_interpose_empty() {
2012 let runtime = setup_runtime();
2013 let expr = runtime.compile("interpose(@, `0`)").unwrap();
2014 let data = json!([]);
2015 let result = expr.search(&data).unwrap();
2016 let arr = result.as_array().unwrap();
2017 assert_eq!(arr.len(), 0);
2018 }
2019
2020 #[test]
2021 fn test_interpose_single() {
2022 let runtime = setup_runtime();
2023 let expr = runtime.compile("interpose(@, `0`)").unwrap();
2024 let data = json!([1]);
2025 let result = expr.search(&data).unwrap();
2026 let arr = result.as_array().unwrap();
2027 assert_eq!(arr.len(), 1);
2028 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2029 }
2030
2031 #[test]
2032 fn test_interpose_string_separator() {
2033 let runtime = setup_runtime();
2034 let expr = runtime.compile("interpose(@, `\"-\"`)").unwrap();
2035 let data = json!(["a", "b", "c"]);
2036 let result = expr.search(&data).unwrap();
2037 let arr = result.as_array().unwrap();
2038 assert_eq!(arr.len(), 5);
2039 assert_eq!(arr[0].as_str().unwrap(), "a");
2040 assert_eq!(arr[1].as_str().unwrap(), "-");
2041 assert_eq!(arr[2].as_str().unwrap(), "b");
2042 assert_eq!(arr[3].as_str().unwrap(), "-");
2043 assert_eq!(arr[4].as_str().unwrap(), "c");
2044 }
2045
2046 #[test]
2047 fn test_zipmap() {
2048 let runtime = setup_runtime();
2049 let expr = runtime
2050 .compile("zipmap(`[\"a\", \"b\", \"c\"]`, `[1, 2, 3]`)")
2051 .unwrap();
2052 let data = json!(null);
2053 let result = expr.search(&data).unwrap();
2054 let obj = result.as_object().unwrap();
2055 assert_eq!(obj.len(), 3);
2056 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 1);
2057 assert_eq!(obj.get("b").unwrap().as_f64().unwrap() as i64, 2);
2058 assert_eq!(obj.get("c").unwrap().as_f64().unwrap() as i64, 3);
2059 }
2060
2061 #[test]
2062 fn test_zipmap_unequal_lengths() {
2063 let runtime = setup_runtime();
2064 let expr = runtime
2066 .compile("zipmap(`[\"x\", \"y\"]`, `[10, 20, 30]`)")
2067 .unwrap();
2068 let data = json!(null);
2069 let result = expr.search(&data).unwrap();
2070 let obj = result.as_object().unwrap();
2071 assert_eq!(obj.len(), 2);
2072 assert_eq!(obj.get("x").unwrap().as_f64().unwrap() as i64, 10);
2073 assert_eq!(obj.get("y").unwrap().as_f64().unwrap() as i64, 20);
2074 }
2075
2076 #[test]
2077 fn test_zipmap_empty() {
2078 let runtime = setup_runtime();
2079 let expr = runtime.compile("zipmap(`[]`, `[]`)").unwrap();
2080 let data = json!(null);
2081 let result = expr.search(&data).unwrap();
2082 let obj = result.as_object().unwrap();
2083 assert_eq!(obj.len(), 0);
2084 }
2085
2086 #[test]
2087 fn test_partition_by() {
2088 let runtime = setup_runtime();
2089 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2091 let data: serde_json::Value = serde_json::from_str(
2092 r#"[{"type": "a", "v": 1}, {"type": "a", "v": 2}, {"type": "b", "v": 3}, {"type": "a", "v": 4}]"#,
2093 )
2094 .unwrap();
2095 let result = expr.search(&data).unwrap();
2096 let arr = result.as_array().unwrap();
2097 assert_eq!(arr.len(), 3);
2098
2099 let partition1 = arr[0].as_array().unwrap();
2100 assert_eq!(partition1.len(), 2); let partition2 = arr[1].as_array().unwrap();
2103 assert_eq!(partition2.len(), 1); let partition3 = arr[2].as_array().unwrap();
2106 assert_eq!(partition3.len(), 1); }
2108
2109 #[test]
2110 fn test_partition_by_primitives() {
2111 let runtime = setup_runtime();
2112 let expr = runtime.compile(r#"partition_by(@, `"_"`)"#).unwrap();
2114 let data = json!([1, 1, 2, 2, 1, 1]);
2115 let result = expr.search(&data).unwrap();
2116 let arr = result.as_array().unwrap();
2117 assert_eq!(arr.len(), 3);
2118
2119 let partition1 = arr[0].as_array().unwrap();
2120 assert_eq!(partition1.len(), 2);
2121 assert_eq!(partition1[0].as_f64().unwrap() as i64, 1);
2122
2123 let partition2 = arr[1].as_array().unwrap();
2124 assert_eq!(partition2.len(), 2);
2125 assert_eq!(partition2[0].as_f64().unwrap() as i64, 2);
2126
2127 let partition3 = arr[2].as_array().unwrap();
2128 assert_eq!(partition3.len(), 2);
2129 assert_eq!(partition3[0].as_f64().unwrap() as i64, 1);
2130 }
2131
2132 #[test]
2133 fn test_partition_by_empty() {
2134 let runtime = setup_runtime();
2135 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2136 let data = json!([]);
2137 let result = expr.search(&data).unwrap();
2138 let arr = result.as_array().unwrap();
2139 assert_eq!(arr.len(), 0);
2140 }
2141
2142 #[test]
2143 fn test_partition_by_single() {
2144 let runtime = setup_runtime();
2145 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2146 let data: serde_json::Value = serde_json::from_str(r#"[{"type": "a"}]"#).unwrap();
2147 let result = expr.search(&data).unwrap();
2148 let arr = result.as_array().unwrap();
2149 assert_eq!(arr.len(), 1);
2150 let partition1 = arr[0].as_array().unwrap();
2151 assert_eq!(partition1.len(), 1);
2152 }
2153
2154 #[test]
2155 fn test_dedupe() {
2156 let runtime = setup_runtime();
2157 let expr = runtime.compile("dedupe(@)").unwrap();
2158 let data = json!([1, 1, 2, 2, 1, 1]);
2159 let result = expr.search(&data).unwrap();
2160 let arr = result.as_array().unwrap();
2161 assert_eq!(arr.len(), 3);
2162 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2163 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
2164 assert_eq!(arr[2].as_f64().unwrap() as i64, 1);
2165 }
2166
2167 #[test]
2168 fn test_dedupe_empty() {
2169 let runtime = setup_runtime();
2170 let expr = runtime.compile("dedupe(@)").unwrap();
2171 let data = json!([]);
2172 let result = expr.search(&data).unwrap();
2173 let arr = result.as_array().unwrap();
2174 assert_eq!(arr.len(), 0);
2175 }
2176
2177 #[test]
2178 fn test_dedupe_no_consecutive() {
2179 let runtime = setup_runtime();
2180 let expr = runtime.compile("dedupe(@)").unwrap();
2181 let data = json!([1, 2, 3]);
2182 let result = expr.search(&data).unwrap();
2183 let arr = result.as_array().unwrap();
2184 assert_eq!(arr.len(), 3);
2185 }
2186
2187 #[test]
2188 fn test_dedupe_strings() {
2189 let runtime = setup_runtime();
2190 let expr = runtime.compile("dedupe(@)").unwrap();
2191 let data = json!(["a", "a", "b", "a"]);
2192 let result = expr.search(&data).unwrap();
2193 let arr = result.as_array().unwrap();
2194 assert_eq!(arr.len(), 3);
2195 assert_eq!(arr[0].as_str().unwrap(), "a");
2196 assert_eq!(arr[1].as_str().unwrap(), "b");
2197 assert_eq!(arr[2].as_str().unwrap(), "a");
2198 }
2199
2200 #[test]
2201 fn test_dedupe_objects() {
2202 let runtime = setup_runtime();
2203 let expr = runtime.compile("dedupe(@)").unwrap();
2204 let data: serde_json::Value =
2205 serde_json::from_str(r#"[{"x": 1}, {"x": 1}, {"x": 2}, {"x": 1}]"#).unwrap();
2206 let result = expr.search(&data).unwrap();
2207 let arr = result.as_array().unwrap();
2208 assert_eq!(arr.len(), 3);
2209 }
2210
2211 #[test]
2212 fn test_dedupe_all_same() {
2213 let runtime = setup_runtime();
2214 let expr = runtime.compile("dedupe(@)").unwrap();
2215 let data = json!([1, 1, 1]);
2216 let result = expr.search(&data).unwrap();
2217 let arr = result.as_array().unwrap();
2218 assert_eq!(arr.len(), 1);
2219 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2220 }
2221
2222 #[test]
2223 fn test_zipmap_duplicate_keys() {
2224 let runtime = setup_runtime();
2226 let expr = runtime
2227 .compile("zipmap(`[\"a\", \"b\", \"a\"]`, `[1, 2, 3]`)")
2228 .unwrap();
2229 let data = json!(null);
2230 let result = expr.search(&data).unwrap();
2231 let obj = result.as_object().unwrap();
2232 assert_eq!(obj.len(), 2);
2233 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 3); assert_eq!(obj.get("b").unwrap().as_f64().unwrap() as i64, 2);
2235 }
2236
2237 #[test]
2238 fn test_zipmap_values_longer() {
2239 let runtime = setup_runtime();
2240 let expr = runtime.compile("zipmap(`[\"a\"]`, `[1, 2, 3]`)").unwrap();
2241 let data = json!(null);
2242 let result = expr.search(&data).unwrap();
2243 let obj = result.as_object().unwrap();
2244 assert_eq!(obj.len(), 1);
2245 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 1);
2246 }
2247
2248 #[test]
2249 fn test_partition_by_missing_field() {
2250 let runtime = setup_runtime();
2251 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2252 let data: serde_json::Value =
2254 serde_json::from_str(r#"[{"type": "a"}, {"name": "no-type"}, {"type": "a"}]"#).unwrap();
2255 let result = expr.search(&data).unwrap();
2256 let arr = result.as_array().unwrap();
2257 assert_eq!(arr.len(), 3);
2259 }
2260
2261 #[test]
2262 fn test_partition_by_all_same() {
2263 let runtime = setup_runtime();
2264 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2265 let data: serde_json::Value =
2266 serde_json::from_str(r#"[{"type": "a"}, {"type": "a"}, {"type": "a"}]"#).unwrap();
2267 let result = expr.search(&data).unwrap();
2268 let arr = result.as_array().unwrap();
2269 assert_eq!(arr.len(), 1);
2270 let partition = arr[0].as_array().unwrap();
2271 assert_eq!(partition.len(), 3);
2272 }
2273
2274 #[test]
2275 fn test_interpose_null_separator() {
2276 let runtime = setup_runtime();
2277 let expr = runtime.compile("interpose(@, `null`)").unwrap();
2278 let data = json!([1, 2]);
2279 let result = expr.search(&data).unwrap();
2280 let arr = result.as_array().unwrap();
2281 assert_eq!(arr.len(), 3);
2282 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2283 assert!(arr[1].is_null());
2284 assert_eq!(arr[2].as_f64().unwrap() as i64, 2);
2285 }
2286
2287 #[test]
2288 fn test_interpose_object_separator() {
2289 let runtime = setup_runtime();
2290 let expr = runtime.compile(r#"interpose(@, `{"sep": true}`)"#).unwrap();
2291 let data = json!([1, 2]);
2292 let result = expr.search(&data).unwrap();
2293 let arr = result.as_array().unwrap();
2294 assert_eq!(arr.len(), 3);
2295 assert!(arr[1].as_object().is_some());
2296 }
2297
2298 #[test]
2303 fn test_zip_basic() {
2304 let runtime = setup_runtime();
2305 let data: serde_json::Value =
2306 serde_json::from_str(r#"{"a": [1, 2, 3], "b": ["x", "y", "z"]}"#).unwrap();
2307 let expr = runtime.compile("zip(a, b)").unwrap();
2308 let result = expr.search(&data).unwrap();
2309 let arr = result.as_array().unwrap();
2310 assert_eq!(arr.len(), 3);
2311 assert_eq!(arr[0].as_array().unwrap()[0].as_f64().unwrap() as i64, 1);
2312 assert_eq!(arr[0].as_array().unwrap()[1].as_str().unwrap(), "x");
2313 }
2314
2315 #[test]
2316 fn test_zip_unequal_lengths() {
2317 let runtime = setup_runtime();
2318 let data: serde_json::Value =
2319 serde_json::from_str(r#"{"a": [1, 2], "b": ["x", "y", "z"]}"#).unwrap();
2320 let expr = runtime.compile("zip(a, b)").unwrap();
2321 let result = expr.search(&data).unwrap();
2322 let arr = result.as_array().unwrap();
2323 assert_eq!(arr.len(), 2);
2325 }
2326
2327 #[test]
2328 fn test_zip_empty_array() {
2329 let runtime = setup_runtime();
2330 let data: serde_json::Value = serde_json::from_str(r#"{"a": [], "b": [1, 2, 3]}"#).unwrap();
2331 let expr = runtime.compile("zip(a, b)").unwrap();
2332 let result = expr.search(&data).unwrap();
2333 let arr = result.as_array().unwrap();
2334 assert_eq!(arr.len(), 0);
2335 }
2336
2337 #[test]
2338 fn test_zip_with_objects() {
2339 let runtime = setup_runtime();
2340 let data: serde_json::Value =
2341 serde_json::from_str(r#"{"names": ["Alice", "Bob"], "scores": [95, 87]}"#).unwrap();
2342 let expr = runtime.compile("zip(names, scores)").unwrap();
2343 let result = expr.search(&data).unwrap();
2344 let arr = result.as_array().unwrap();
2345 assert_eq!(arr.len(), 2);
2346 assert_eq!(arr[0].as_array().unwrap()[0].as_str().unwrap(), "Alice");
2347 assert_eq!(arr[0].as_array().unwrap()[1].as_f64().unwrap() as i64, 95);
2348 }
2349
2350 #[test]
2355 fn test_chunk_basic() {
2356 let runtime = setup_runtime();
2357 let data = json!([1, 2, 3, 4, 5]);
2358 let expr = runtime.compile("chunk(@, `2`)").unwrap();
2359 let result = expr.search(&data).unwrap();
2360 let arr = result.as_array().unwrap();
2361 assert_eq!(arr.len(), 3); assert_eq!(arr[0].as_array().unwrap().len(), 2);
2363 assert_eq!(arr[2].as_array().unwrap().len(), 1);
2364 }
2365
2366 #[test]
2367 fn test_chunk_exact_fit() {
2368 let runtime = setup_runtime();
2369 let data = json!([1, 2, 3, 4, 5, 6]);
2370 let expr = runtime.compile("chunk(@, `3`)").unwrap();
2371 let result = expr.search(&data).unwrap();
2372 let arr = result.as_array().unwrap();
2373 assert_eq!(arr.len(), 2);
2374 assert_eq!(arr[0].as_array().unwrap().len(), 3);
2375 assert_eq!(arr[1].as_array().unwrap().len(), 3);
2376 }
2377
2378 #[test]
2379 fn test_chunk_size_larger_than_array() {
2380 let runtime = setup_runtime();
2381 let data = json!([1, 2, 3]);
2382 let expr = runtime.compile("chunk(@, `10`)").unwrap();
2383 let result = expr.search(&data).unwrap();
2384 let arr = result.as_array().unwrap();
2385 assert_eq!(arr.len(), 1);
2386 assert_eq!(arr[0].as_array().unwrap().len(), 3);
2387 }
2388
2389 #[test]
2390 fn test_chunk_size_one() {
2391 let runtime = setup_runtime();
2392 let data = json!([1, 2, 3]);
2393 let expr = runtime.compile("chunk(@, `1`)").unwrap();
2394 let result = expr.search(&data).unwrap();
2395 let arr = result.as_array().unwrap();
2396 assert_eq!(arr.len(), 3);
2397 }
2398
2399 #[test]
2400 fn test_chunk_and_process_pipeline() {
2401 let runtime = setup_runtime();
2402 let data = json!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2403 let expr = runtime.compile("chunk(@, `3`)").unwrap();
2404 let result = expr.search(&data).unwrap();
2405 let arr = result.as_array().unwrap();
2406 assert_eq!(arr.len(), 4);
2408 }
2409
2410 #[test]
2415 fn test_take_basic() {
2416 let runtime = setup_runtime();
2417 let data = json!([1, 2, 3, 4, 5]);
2418 let expr = runtime.compile("take(@, `3`)").unwrap();
2419 let result = expr.search(&data).unwrap();
2420 let arr = result.as_array().unwrap();
2421 assert_eq!(arr.len(), 3);
2422 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2423 assert_eq!(arr[2].as_f64().unwrap() as i64, 3);
2424 }
2425
2426 #[test]
2427 fn test_take_more_than_length() {
2428 let runtime = setup_runtime();
2429 let data = json!([1, 2]);
2430 let expr = runtime.compile("take(@, `10`)").unwrap();
2431 let result = expr.search(&data).unwrap();
2432 let arr = result.as_array().unwrap();
2433 assert_eq!(arr.len(), 2);
2434 }
2435
2436 #[test]
2437 fn test_take_zero() {
2438 let runtime = setup_runtime();
2439 let data = json!([1, 2, 3]);
2440 let expr = runtime.compile("take(@, `0`)").unwrap();
2441 let result = expr.search(&data).unwrap();
2442 let arr = result.as_array().unwrap();
2443 assert_eq!(arr.len(), 0);
2444 }
2445
2446 #[test]
2451 fn test_drop_basic() {
2452 let runtime = setup_runtime();
2453 let data = json!([1, 2, 3, 4, 5]);
2454 let expr = runtime.compile("drop(@, `2`)").unwrap();
2455 let result = expr.search(&data).unwrap();
2456 let arr = result.as_array().unwrap();
2457 assert_eq!(arr.len(), 3);
2458 assert_eq!(arr[0].as_f64().unwrap() as i64, 3);
2459 }
2460
2461 #[test]
2462 fn test_drop_more_than_length() {
2463 let runtime = setup_runtime();
2464 let data = json!([1, 2]);
2465 let expr = runtime.compile("drop(@, `10`)").unwrap();
2466 let result = expr.search(&data).unwrap();
2467 let arr = result.as_array().unwrap();
2468 assert_eq!(arr.len(), 0);
2469 }
2470
2471 #[test]
2472 fn test_drop_zero() {
2473 let runtime = setup_runtime();
2474 let data = json!([1, 2, 3]);
2475 let expr = runtime.compile("drop(@, `0`)").unwrap();
2476 let result = expr.search(&data).unwrap();
2477 let arr = result.as_array().unwrap();
2478 assert_eq!(arr.len(), 3);
2479 }
2480
2481 #[test]
2486 fn test_flatten_deep_basic() {
2487 let runtime = setup_runtime();
2488 let data = json!([[1, 2], [3, 4]]);
2489 let expr = runtime.compile("flatten_deep(@)").unwrap();
2490 let result = expr.search(&data).unwrap();
2491 let arr = result.as_array().unwrap();
2492 assert_eq!(arr.len(), 4);
2493 }
2494
2495 #[test]
2496 fn test_flatten_deep_nested() {
2497 let runtime = setup_runtime();
2498 let data = json!([1, [2, [3, [4, [5]]]]]);
2499 let expr = runtime.compile("flatten_deep(@)").unwrap();
2500 let result = expr.search(&data).unwrap();
2501 let arr = result.as_array().unwrap();
2502 assert_eq!(arr.len(), 5);
2503 assert_eq!(arr[4].as_f64().unwrap() as i64, 5);
2504 }
2505
2506 #[test]
2507 fn test_flatten_deep_already_flat() {
2508 let runtime = setup_runtime();
2509 let data = json!([1, 2, 3]);
2510 let expr = runtime.compile("flatten_deep(@)").unwrap();
2511 let result = expr.search(&data).unwrap();
2512 let arr = result.as_array().unwrap();
2513 assert_eq!(arr.len(), 3);
2514 }
2515
2516 #[test]
2517 fn test_flatten_deep_mixed() {
2518 let runtime = setup_runtime();
2519 let data = json!([1, [2, 3], [[4]], [[[5, 6]]]]);
2520 let expr = runtime.compile("flatten_deep(@)").unwrap();
2521 let result = expr.search(&data).unwrap();
2522 let arr = result.as_array().unwrap();
2523 assert_eq!(arr.len(), 6);
2524 }
2525
2526 #[test]
2531 fn test_compact_basic() {
2532 let runtime = setup_runtime();
2533 let data = json!([1, null, 2, false, 3]);
2534 let expr = runtime.compile("compact(@)").unwrap();
2535 let result = expr.search(&data).unwrap();
2536 let arr = result.as_array().unwrap();
2537 assert_eq!(arr.len(), 3);
2538 }
2539
2540 #[test]
2541 fn test_compact_keeps_zero_and_empty_string() {
2542 let runtime = setup_runtime();
2543 let data = json!([0, "", null, true]);
2544 let expr = runtime.compile("compact(@)").unwrap();
2545 let result = expr.search(&data).unwrap();
2546 let arr = result.as_array().unwrap();
2547 assert_eq!(arr.len(), 3); }
2549
2550 #[test]
2551 fn test_compact_all_falsy() {
2552 let runtime = setup_runtime();
2553 let data = json!([null, false, null]);
2554 let expr = runtime.compile("compact(@)").unwrap();
2555 let result = expr.search(&data).unwrap();
2556 let arr = result.as_array().unwrap();
2557 assert_eq!(arr.len(), 0);
2558 }
2559
2560 #[test]
2565 fn test_index_at_positive() {
2566 let runtime = setup_runtime();
2567 let data = json!(["a", "b", "c", "d"]);
2568 let expr = runtime.compile("index_at(@, `2`)").unwrap();
2569 let result = expr.search(&data).unwrap();
2570 assert_eq!(result.as_str().unwrap(), "c");
2571 }
2572
2573 #[test]
2574 fn test_index_at_negative() {
2575 let runtime = setup_runtime();
2576 let data = json!(["a", "b", "c", "d"]);
2577 let expr = runtime.compile("index_at(@, `-1`)").unwrap();
2578 let result = expr.search(&data).unwrap();
2579 assert_eq!(result.as_str().unwrap(), "d");
2580 }
2581
2582 #[test]
2583 fn test_index_at_negative_second() {
2584 let runtime = setup_runtime();
2585 let data = json!(["a", "b", "c", "d"]);
2586 let expr = runtime.compile("index_at(@, `-2`)").unwrap();
2587 let result = expr.search(&data).unwrap();
2588 assert_eq!(result.as_str().unwrap(), "c");
2589 }
2590
2591 #[test]
2592 fn test_index_at_out_of_bounds() {
2593 let runtime = setup_runtime();
2594 let data = json!(["a", "b", "c"]);
2595 let expr = runtime.compile("index_at(@, `10`)").unwrap();
2596 let result = expr.search(&data).unwrap();
2597 assert!(result.is_null());
2598 }
2599
2600 #[test]
2605 fn test_includes_number() {
2606 let runtime = setup_runtime();
2607 let data = json!([1, 2, 3, 4, 5]);
2608 let expr = runtime.compile("includes(@, `3`)").unwrap();
2609 let result = expr.search(&data).unwrap();
2610 assert!(result.as_bool().unwrap());
2611 }
2612
2613 #[test]
2614 fn test_includes_not_found() {
2615 let runtime = setup_runtime();
2616 let data = json!([1, 2, 3]);
2617 let expr = runtime.compile("includes(@, `10`)").unwrap();
2618 let result = expr.search(&data).unwrap();
2619 assert!(!result.as_bool().unwrap());
2620 }
2621
2622 #[test]
2623 fn test_includes_string() {
2624 let runtime = setup_runtime();
2625 let data = json!(["apple", "banana", "cherry"]);
2626 let expr = runtime.compile(r#"includes(@, `"banana"`)"#).unwrap();
2627 let result = expr.search(&data).unwrap();
2628 assert!(result.as_bool().unwrap());
2629 }
2630
2631 #[test]
2632 fn test_includes_object() {
2633 let runtime = setup_runtime();
2634 let data = json!([{"a": 1}, {"b": 2}]);
2635 let expr = runtime.compile(r#"includes(@, `{"a": 1}`)"#).unwrap();
2636 let result = expr.search(&data).unwrap();
2637 assert!(result.as_bool().unwrap());
2638 }
2639
2640 #[test]
2645 fn test_find_index_found() {
2646 let runtime = setup_runtime();
2647 let data = json!(["a", "b", "c", "d"]);
2648 let expr = runtime.compile(r#"find_index(@, `"c"`)"#).unwrap();
2649 let result = expr.search(&data).unwrap();
2650 assert_eq!(result.as_f64().unwrap() as i64, 2);
2651 }
2652
2653 #[test]
2654 fn test_find_index_not_found() {
2655 let runtime = setup_runtime();
2656 let data = json!(["a", "b", "c"]);
2657 let expr = runtime.compile(r#"find_index(@, `"z"`)"#).unwrap();
2658 let result = expr.search(&data).unwrap();
2659 assert_eq!(result.as_f64().unwrap() as i64, -1);
2660 }
2661
2662 #[test]
2667 fn test_group_by_basic() {
2668 let runtime = setup_runtime();
2669 let data: serde_json::Value = serde_json::from_str(
2670 r#"[{"type": "a", "v": 1}, {"type": "b", "v": 2}, {"type": "a", "v": 3}]"#,
2671 )
2672 .unwrap();
2673 let expr = runtime.compile(r#"group_by(@, `"type"`)"#).unwrap();
2674 let result = expr.search(&data).unwrap();
2675 let obj = result.as_object().unwrap();
2676 assert_eq!(obj.get("a").unwrap().as_array().unwrap().len(), 2);
2677 assert_eq!(obj.get("b").unwrap().as_array().unwrap().len(), 1);
2678 }
2679
2680 #[test]
2685 fn test_index_by_basic() {
2686 let runtime = setup_runtime();
2687 let data: serde_json::Value =
2688 serde_json::from_str(r#"[{"id": 1, "name": "alice"}, {"id": 2, "name": "bob"}]"#)
2689 .unwrap();
2690 let expr = runtime.compile(r#"index_by(@, `"id"`)"#).unwrap();
2691 let result = expr.search(&data).unwrap();
2692 let obj = result.as_object().unwrap();
2693 assert_eq!(obj.len(), 2);
2694 let alice = obj.get("1").unwrap().as_object().unwrap();
2696 assert_eq!(alice.get("name").unwrap().as_str().unwrap(), "alice");
2697 let bob = obj.get("2").unwrap().as_object().unwrap();
2698 assert_eq!(bob.get("name").unwrap().as_str().unwrap(), "bob");
2699 }
2700
2701 #[test]
2702 fn test_index_by_string_key() {
2703 let runtime = setup_runtime();
2704 let data: serde_json::Value = serde_json::from_str(
2705 r#"[{"code": "US", "name": "United States"}, {"code": "UK", "name": "United Kingdom"}]"#,
2706 )
2707 .unwrap();
2708 let expr = runtime.compile(r#"index_by(@, `"code"`)"#).unwrap();
2709 let result = expr.search(&data).unwrap();
2710 let obj = result.as_object().unwrap();
2711 assert_eq!(obj.len(), 2);
2712 let us = obj.get("US").unwrap().as_object().unwrap();
2713 assert_eq!(us.get("name").unwrap().as_str().unwrap(), "United States");
2714 }
2715
2716 #[test]
2717 fn test_index_by_duplicate_keys() {
2718 let runtime = setup_runtime();
2720 let data: serde_json::Value = serde_json::from_str(
2721 r#"[{"type": "a", "v": 1}, {"type": "a", "v": 2}, {"type": "a", "v": 3}]"#,
2722 )
2723 .unwrap();
2724 let expr = runtime.compile(r#"index_by(@, `"type"`)"#).unwrap();
2725 let result = expr.search(&data).unwrap();
2726 let obj = result.as_object().unwrap();
2727 assert_eq!(obj.len(), 1);
2728 let a = obj.get("a").unwrap().as_object().unwrap();
2730 assert_eq!(a.get("v").unwrap().as_f64().unwrap() as i64, 3);
2731 }
2732
2733 #[test]
2734 fn test_index_by_missing_key() {
2735 let runtime = setup_runtime();
2737 let data: serde_json::Value = serde_json::from_str(
2738 r#"[{"id": 1, "name": "alice"}, {"name": "bob"}, {"id": 3, "name": "charlie"}]"#,
2739 )
2740 .unwrap();
2741 let expr = runtime.compile(r#"index_by(@, `"id"`)"#).unwrap();
2742 let result = expr.search(&data).unwrap();
2743 let obj = result.as_object().unwrap();
2744 assert_eq!(obj.len(), 2);
2745 assert!(obj.contains_key("1"));
2746 assert!(obj.contains_key("3"));
2747 assert!(!obj.contains_key("2")); }
2749
2750 #[test]
2751 fn test_index_by_empty_array() {
2752 let runtime = setup_runtime();
2753 let data = json!([]);
2754 let expr = runtime.compile(r#"index_by(@, `"id"`)"#).unwrap();
2755 let result = expr.search(&data).unwrap();
2756 let obj = result.as_object().unwrap();
2757 assert!(obj.is_empty());
2758 }
2759
2760 #[test]
2765 fn test_difference() {
2766 let runtime = setup_runtime();
2767 let data: serde_json::Value =
2768 serde_json::from_str(r#"{"a": [1, 2, 3, 4], "b": [2, 4]}"#).unwrap();
2769 let expr = runtime.compile("difference(a, b)").unwrap();
2770 let result = expr.search(&data).unwrap();
2771 let arr = result.as_array().unwrap();
2772 assert_eq!(arr.len(), 2); }
2774
2775 #[test]
2776 fn test_intersection() {
2777 let runtime = setup_runtime();
2778 let data: serde_json::Value =
2779 serde_json::from_str(r#"{"a": [1, 2, 3], "b": [2, 3, 4]}"#).unwrap();
2780 let expr = runtime.compile("intersection(a, b)").unwrap();
2781 let result = expr.search(&data).unwrap();
2782 let arr = result.as_array().unwrap();
2783 assert_eq!(arr.len(), 2); }
2785
2786 #[test]
2787 fn test_union() {
2788 let runtime = setup_runtime();
2789 let data: serde_json::Value =
2790 serde_json::from_str(r#"{"a": [1, 2], "b": [2, 3]}"#).unwrap();
2791 let expr = runtime.compile("union(a, b)").unwrap();
2792 let result = expr.search(&data).unwrap();
2793 let arr = result.as_array().unwrap();
2794 assert_eq!(arr.len(), 3); }
2796
2797 #[test]
2802 fn test_frequencies_basic() {
2803 let runtime = setup_runtime();
2804 let data = json!(["a", "b", "a", "c", "a", "b"]);
2805 let expr = runtime.compile("frequencies(@)").unwrap();
2806 let result = expr.search(&data).unwrap();
2807 let obj = result.as_object().unwrap();
2808 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 3);
2809 assert_eq!(obj.get("b").unwrap().as_f64().unwrap() as i64, 2);
2810 assert_eq!(obj.get("c").unwrap().as_f64().unwrap() as i64, 1);
2811 }
2812
2813 #[test]
2814 fn test_frequencies_numbers() {
2815 let runtime = setup_runtime();
2816 let data = json!([1, 2, 1, 1, 2, 3]);
2817 let expr = runtime.compile("frequencies(@)").unwrap();
2818 let result = expr.search(&data).unwrap();
2819 let obj = result.as_object().unwrap();
2820 assert_eq!(obj.get("1").unwrap().as_f64().unwrap() as i64, 3);
2821 assert_eq!(obj.get("2").unwrap().as_f64().unwrap() as i64, 2);
2822 }
2823
2824 #[test]
2829 fn test_mode_basic() {
2830 let runtime = setup_runtime();
2831 let data = json!([1, 2, 2, 3, 2, 4]);
2832 let expr = runtime.compile("mode(@)").unwrap();
2833 let result = expr.search(&data).unwrap();
2834 assert_eq!(result.as_f64().unwrap() as i64, 2);
2835 }
2836
2837 #[test]
2838 fn test_mode_empty() {
2839 let runtime = setup_runtime();
2840 let data = json!([]);
2841 let expr = runtime.compile("mode(@)").unwrap();
2842 let result = expr.search(&data).unwrap();
2843 assert!(result.is_null());
2844 }
2845
2846 #[test]
2851 fn test_cartesian_basic() {
2852 let runtime = setup_runtime();
2853 let data: serde_json::Value =
2854 serde_json::from_str(r#"{"a": [1, 2], "b": ["x", "y"]}"#).unwrap();
2855 let expr = runtime.compile("cartesian(a, b)").unwrap();
2856 let result = expr.search(&data).unwrap();
2857 let arr = result.as_array().unwrap();
2858 assert_eq!(arr.len(), 4); }
2860
2861 #[test]
2862 fn test_cartesian_empty() {
2863 let runtime = setup_runtime();
2864 let data: serde_json::Value = serde_json::from_str(r#"{"a": [], "b": [1, 2]}"#).unwrap();
2865 let expr = runtime.compile("cartesian(a, b)").unwrap();
2866 let result = expr.search(&data).unwrap();
2867 let arr = result.as_array().unwrap();
2868 assert_eq!(arr.len(), 0);
2869 }
2870
2871 #[test]
2872 fn test_cartesian_n_way_two_arrays() {
2873 let runtime = setup_runtime();
2874 let data = json!([[1, 2], ["a", "b"]]);
2875 let expr = runtime.compile("cartesian(@)").unwrap();
2876 let result = expr.search(&data).unwrap();
2877 let arr = result.as_array().unwrap();
2878 assert_eq!(arr.len(), 4); }
2880
2881 #[test]
2882 fn test_cartesian_n_way_three_arrays() {
2883 let runtime = setup_runtime();
2884 let data = json!([[1, 2], ["a", "b"], [true, false]]);
2885 let expr = runtime.compile("cartesian(@)").unwrap();
2886 let result = expr.search(&data).unwrap();
2887 let arr = result.as_array().unwrap();
2888 assert_eq!(arr.len(), 8); }
2890
2891 #[test]
2892 fn test_cartesian_n_way_single_array() {
2893 let runtime = setup_runtime();
2894 let data = json!([[1, 2, 3]]);
2895 let expr = runtime.compile("cartesian(@)").unwrap();
2896 let result = expr.search(&data).unwrap();
2897 let arr = result.as_array().unwrap();
2898 assert_eq!(arr.len(), 3); }
2900
2901 #[test]
2902 fn test_cartesian_n_way_empty() {
2903 let runtime = setup_runtime();
2904 let data = json!([]);
2905 let expr = runtime.compile("cartesian(@)").unwrap();
2906 let result = expr.search(&data).unwrap();
2907 let arr = result.as_array().unwrap();
2908 assert_eq!(arr.len(), 0);
2909 }
2910
2911 #[test]
2916 fn test_first_empty_array() {
2917 let runtime = setup_runtime();
2918 let data = json!([]);
2919 let expr = runtime.compile("first(@)").unwrap();
2920 let result = expr.search(&data).unwrap();
2921 assert!(result.is_null());
2922 }
2923
2924 #[test]
2925 fn test_last_empty_array() {
2926 let runtime = setup_runtime();
2927 let data = json!([]);
2928 let expr = runtime.compile("last(@)").unwrap();
2929 let result = expr.search(&data).unwrap();
2930 assert!(result.is_null());
2931 }
2932
2933 #[test]
2934 fn test_unique_preserves_order() {
2935 let runtime = setup_runtime();
2936 let data = json!(["c", "a", "b", "a", "c"]);
2937 let expr = runtime.compile("unique(@)").unwrap();
2938 let result = expr.search(&data).unwrap();
2939 let arr = result.as_array().unwrap();
2940 assert_eq!(arr.len(), 3);
2941 assert_eq!(arr[0].as_str().unwrap(), "c");
2942 assert_eq!(arr[1].as_str().unwrap(), "a");
2943 assert_eq!(arr[2].as_str().unwrap(), "b");
2944 }
2945
2946 #[test]
2947 fn test_unique_different_types() {
2948 let runtime = setup_runtime();
2949 let data = json!([1, "1", 1, "1"]);
2950 let expr = runtime.compile("unique(@)").unwrap();
2951 let result = expr.search(&data).unwrap();
2952 let arr = result.as_array().unwrap();
2953 assert_eq!(arr.len(), 2); }
2955
2956 #[test]
2957 fn test_range_with_step() {
2958 let runtime = setup_runtime();
2959 let data = json!(null);
2960 let expr = runtime.compile("range(`1`, `10`, `2`)").unwrap();
2961 let result = expr.search(&data).unwrap();
2962 let arr = result.as_array().unwrap();
2963 assert_eq!(arr.len(), 5); assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2965 assert_eq!(arr[4].as_f64().unwrap() as i64, 9);
2966 }
2967
2968 #[test]
2969 fn test_range_descending() {
2970 let runtime = setup_runtime();
2971 let data = json!(null);
2972 let expr = runtime.compile("range(`5`, `0`, `-1`)").unwrap();
2973 let result = expr.search(&data).unwrap();
2974 let arr = result.as_array().unwrap();
2975 assert_eq!(arr.len(), 5); assert_eq!(arr[0].as_f64().unwrap() as i64, 5);
2977 assert_eq!(arr[4].as_f64().unwrap() as i64, 1);
2978 }
2979
2980 #[test]
2985 fn test_pipeline_unique_sort() {
2986 let runtime = setup_runtime();
2987 let data = json!(["redis", "database", "redis", "nosql", "database"]);
2988 let expr = runtime.compile("unique(@) | sort(@)").unwrap();
2989 let result = expr.search(&data).unwrap();
2990 let arr = result.as_array().unwrap();
2991 assert_eq!(arr.len(), 3);
2992 assert_eq!(arr[0].as_str().unwrap(), "database");
2993 assert_eq!(arr[1].as_str().unwrap(), "nosql");
2994 assert_eq!(arr[2].as_str().unwrap(), "redis");
2995 }
2996
2997 #[test]
2998 fn test_pipeline_filter_take() {
2999 let runtime = setup_runtime();
3000 let data = json!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
3001 let expr = runtime.compile("[?@ > `3`] | take(@, `3`)").unwrap();
3002 let result = expr.search(&data).unwrap();
3003 let arr = result.as_array().unwrap();
3004 assert_eq!(arr.len(), 3);
3005 assert_eq!(arr[0].as_f64().unwrap() as i64, 4);
3006 assert_eq!(arr[1].as_f64().unwrap() as i64, 5);
3007 assert_eq!(arr[2].as_f64().unwrap() as i64, 6);
3008 }
3009
3010 #[test]
3011 fn test_pipeline_flatten_unique() {
3012 let runtime = setup_runtime();
3013 let data = json!([[1, 2], [2, 3], [3, 4]]);
3014 let expr = runtime.compile("flatten_deep(@) | unique(@)").unwrap();
3015 let result = expr.search(&data).unwrap();
3016 let arr = result.as_array().unwrap();
3017 assert_eq!(arr.len(), 4); }
3019
3020 #[test]
3021 fn test_large_array_processing() {
3022 let runtime = setup_runtime();
3023 let items: Vec<i32> = (1..=1000).collect();
3025 let json_str = serde_json::to_string(&items).unwrap();
3026 let data: serde_json::Value = serde_json::from_str(&json_str).unwrap();
3027
3028 let expr = runtime.compile("length(@)").unwrap();
3029 let result = expr.search(&data).unwrap();
3030 assert_eq!(result.as_f64().unwrap() as i64, 1000);
3031 }
3032
3033 #[test]
3034 fn test_transpose_basic() {
3035 let runtime = setup_runtime();
3036 let data = json!([[1, 2, 3], [4, 5, 6]]);
3037 let expr = runtime.compile("transpose(@)").unwrap();
3038 let result = expr.search(&data).unwrap();
3039 let arr = result.as_array().unwrap();
3040 assert_eq!(arr.len(), 3);
3041 let col0 = arr[0].as_array().unwrap();
3043 assert_eq!(col0[0].as_f64().unwrap() as i64, 1);
3044 assert_eq!(col0[1].as_f64().unwrap() as i64, 4);
3045 let col1 = arr[1].as_array().unwrap();
3047 assert_eq!(col1[0].as_f64().unwrap() as i64, 2);
3048 assert_eq!(col1[1].as_f64().unwrap() as i64, 5);
3049 }
3050
3051 #[test]
3052 fn test_transpose_empty() {
3053 let runtime = setup_runtime();
3054 let data = json!([]);
3055 let expr = runtime.compile("transpose(@)").unwrap();
3056 let result = expr.search(&data).unwrap();
3057 let arr = result.as_array().unwrap();
3058 assert_eq!(arr.len(), 0);
3059 }
3060
3061 #[test]
3062 fn test_transpose_unequal_rows() {
3063 let runtime = setup_runtime();
3064 let data = json!([[1, 2], [3, 4, 5], [6, 7]]);
3065 let expr = runtime.compile("transpose(@)").unwrap();
3066 let result = expr.search(&data).unwrap();
3067 let arr = result.as_array().unwrap();
3068 assert_eq!(arr.len(), 2);
3070 }
3071
3072 #[test]
3073 fn test_pairwise_basic() {
3074 let runtime = setup_runtime();
3075 let data = json!([1, 2, 3, 4]);
3076 let expr = runtime.compile("pairwise(@)").unwrap();
3077 let result = expr.search(&data).unwrap();
3078 let arr = result.as_array().unwrap();
3079 assert_eq!(arr.len(), 3);
3080 let pair0 = arr[0].as_array().unwrap();
3082 assert_eq!(pair0[0].as_f64().unwrap() as i64, 1);
3083 assert_eq!(pair0[1].as_f64().unwrap() as i64, 2);
3084 let pair1 = arr[1].as_array().unwrap();
3086 assert_eq!(pair1[0].as_f64().unwrap() as i64, 2);
3087 assert_eq!(pair1[1].as_f64().unwrap() as i64, 3);
3088 }
3089
3090 #[test]
3091 fn test_pairwise_short_array() {
3092 let runtime = setup_runtime();
3093 let data = json!([1]);
3094 let expr = runtime.compile("pairwise(@)").unwrap();
3095 let result = expr.search(&data).unwrap();
3096 let arr = result.as_array().unwrap();
3097 assert_eq!(arr.len(), 0);
3098 }
3099
3100 #[test]
3101 fn test_sliding_window_alias() {
3102 let runtime = setup_runtime();
3103 let data = json!([1, 2, 3, 4, 5]);
3104 let expr = runtime.compile("sliding_window(@, `3`)").unwrap();
3105 let result = expr.search(&data).unwrap();
3106 let arr = result.as_array().unwrap();
3107 assert_eq!(arr.len(), 3);
3108 let win0 = arr[0].as_array().unwrap();
3110 assert_eq!(win0.len(), 3);
3111 assert_eq!(win0[0].as_f64().unwrap() as i64, 1);
3112 }
3113
3114 #[test]
3116 fn test_indices_array_found() {
3117 let runtime = setup_runtime();
3118 let data = json!([1, 2, 3, 2, 4, 2]);
3119 let expr = runtime.compile("indices_array(@, `2`)").unwrap();
3120 let result = expr.search(&data).unwrap();
3121 let arr = result.as_array().unwrap();
3122 assert_eq!(arr.len(), 3);
3123 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3124 assert_eq!(arr[1].as_f64().unwrap() as i64, 3);
3125 assert_eq!(arr[2].as_f64().unwrap() as i64, 5);
3126 }
3127
3128 #[test]
3129 fn test_indices_array_not_found() {
3130 let runtime = setup_runtime();
3131 let data = json!([1, 2, 3]);
3132 let expr = runtime.compile("indices_array(@, `5`)").unwrap();
3133 let result = expr.search(&data).unwrap();
3134 let arr = result.as_array().unwrap();
3135 assert_eq!(arr.len(), 0);
3136 }
3137
3138 #[test]
3139 fn test_indices_array_strings() {
3140 let runtime = setup_runtime();
3141 let data = json!(["a", "b", "a", "c", "a"]);
3142 let expr = runtime.compile(r#"indices_array(@, `"a"`)"#).unwrap();
3143 let result = expr.search(&data).unwrap();
3144 let arr = result.as_array().unwrap();
3145 assert_eq!(arr.len(), 3);
3146 assert_eq!(arr[0].as_f64().unwrap() as i64, 0);
3147 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
3148 assert_eq!(arr[2].as_f64().unwrap() as i64, 4);
3149 }
3150
3151 #[test]
3153 fn test_inside_array_true() {
3154 let runtime = setup_runtime();
3155 let data: serde_json::Value =
3156 serde_json::from_str(r#"{"a": [1, 2], "b": [1, 2, 3, 4]}"#).unwrap();
3157 let expr = runtime.compile("inside_array(a, b)").unwrap();
3158 let result = expr.search(&data).unwrap();
3159 assert!(result.as_bool().unwrap());
3160 }
3161
3162 #[test]
3163 fn test_inside_array_false() {
3164 let runtime = setup_runtime();
3165 let data: serde_json::Value =
3166 serde_json::from_str(r#"{"a": [1, 5], "b": [1, 2, 3, 4]}"#).unwrap();
3167 let expr = runtime.compile("inside_array(a, b)").unwrap();
3168 let result = expr.search(&data).unwrap();
3169 assert!(!result.as_bool().unwrap());
3170 }
3171
3172 #[test]
3173 fn test_inside_array_empty() {
3174 let runtime = setup_runtime();
3175 let data: serde_json::Value = serde_json::from_str(r#"{"a": [], "b": [1, 2, 3]}"#).unwrap();
3176 let expr = runtime.compile("inside_array(a, b)").unwrap();
3177 let result = expr.search(&data).unwrap();
3178 assert!(result.as_bool().unwrap());
3179 }
3180
3181 #[test]
3183 fn test_bsearch_found() {
3184 let runtime = setup_runtime();
3185 let data = json!([1, 3, 5, 7, 9]);
3186 let expr = runtime.compile("bsearch(@, `5`)").unwrap();
3187 let result = expr.search(&data).unwrap();
3188 assert_eq!(result.as_f64().unwrap() as i64, 2);
3189 }
3190
3191 #[test]
3192 fn test_bsearch_not_found_middle() {
3193 let runtime = setup_runtime();
3194 let data = json!([1, 3, 5, 7, 9]);
3195 let expr = runtime.compile("bsearch(@, `4`)").unwrap();
3196 let result = expr.search(&data).unwrap();
3197 assert_eq!(result.as_f64().unwrap() as i64, -3);
3198 }
3199
3200 #[test]
3201 fn test_bsearch_not_found_start() {
3202 let runtime = setup_runtime();
3203 let data = json!([1, 3, 5, 7, 9]);
3204 let expr = runtime.compile("bsearch(@, `0`)").unwrap();
3205 let result = expr.search(&data).unwrap();
3206 assert_eq!(result.as_f64().unwrap() as i64, -1);
3207 }
3208
3209 #[test]
3210 fn test_bsearch_not_found_end() {
3211 let runtime = setup_runtime();
3212 let data = json!([1, 3, 5, 7, 9]);
3213 let expr = runtime.compile("bsearch(@, `10`)").unwrap();
3214 let result = expr.search(&data).unwrap();
3215 assert_eq!(result.as_f64().unwrap() as i64, -6);
3216 }
3217
3218 #[test]
3219 fn test_bsearch_empty_array() {
3220 let runtime = setup_runtime();
3221 let data = json!([]);
3222 let expr = runtime.compile("bsearch(@, `5`)").unwrap();
3223 let result = expr.search(&data).unwrap();
3224 assert_eq!(result.as_f64().unwrap() as i64, -1);
3225 }
3226
3227 #[test]
3229 fn test_repeat_array_basic() {
3230 let runtime = setup_runtime();
3231 let data = json!(null);
3232 let expr = runtime.compile("repeat_array(`1`, `3`)").unwrap();
3233 let result = expr.search(&data).unwrap();
3234 let arr = result.as_array().unwrap();
3235 assert_eq!(arr.len(), 3);
3236 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3237 assert_eq!(arr[1].as_f64().unwrap() as i64, 1);
3238 assert_eq!(arr[2].as_f64().unwrap() as i64, 1);
3239 }
3240
3241 #[test]
3242 fn test_repeat_array_string() {
3243 let runtime = setup_runtime();
3244 let data = json!(null);
3245 let expr = runtime.compile(r#"repeat_array(`"x"`, `4`)"#).unwrap();
3246 let result = expr.search(&data).unwrap();
3247 let arr = result.as_array().unwrap();
3248 assert_eq!(arr.len(), 4);
3249 assert_eq!(arr[0].as_str().unwrap(), "x");
3250 assert_eq!(arr[3].as_str().unwrap(), "x");
3251 }
3252
3253 #[test]
3254 fn test_repeat_array_zero() {
3255 let runtime = setup_runtime();
3256 let data = json!(null);
3257 let expr = runtime.compile("repeat_array(`1`, `0`)").unwrap();
3258 let result = expr.search(&data).unwrap();
3259 let arr = result.as_array().unwrap();
3260 assert_eq!(arr.len(), 0);
3261 }
3262
3263 #[test]
3264 fn test_repeat_array_object() {
3265 let runtime = setup_runtime();
3266 let data = json!(null);
3267 let expr = runtime.compile(r#"repeat_array(`{"a": 1}`, `2`)"#).unwrap();
3268 let result = expr.search(&data).unwrap();
3269 let arr = result.as_array().unwrap();
3270 assert_eq!(arr.len(), 2);
3271 assert_eq!(
3272 arr[0]
3273 .as_object()
3274 .unwrap()
3275 .get("a")
3276 .unwrap()
3277 .as_f64()
3278 .unwrap() as i64,
3279 1
3280 );
3281 }
3282
3283 #[test]
3285 fn test_cycle_basic() {
3286 let runtime = setup_runtime();
3287 let data = json!([1, 2, 3]);
3288 let expr = runtime.compile("cycle(@, `2`)").unwrap();
3289 let result = expr.search(&data).unwrap();
3290 let arr = result.as_array().unwrap();
3291 assert_eq!(arr.len(), 6);
3292 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3293 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
3294 assert_eq!(arr[2].as_f64().unwrap() as i64, 3);
3295 assert_eq!(arr[3].as_f64().unwrap() as i64, 1);
3296 assert_eq!(arr[4].as_f64().unwrap() as i64, 2);
3297 assert_eq!(arr[5].as_f64().unwrap() as i64, 3);
3298 }
3299
3300 #[test]
3301 fn test_cycle_strings() {
3302 let runtime = setup_runtime();
3303 let data = json!(["a", "b"]);
3304 let expr = runtime.compile("cycle(@, `3`)").unwrap();
3305 let result = expr.search(&data).unwrap();
3306 let arr = result.as_array().unwrap();
3307 assert_eq!(arr.len(), 6);
3308 assert_eq!(arr[0].as_str().unwrap(), "a");
3309 assert_eq!(arr[1].as_str().unwrap(), "b");
3310 assert_eq!(arr[2].as_str().unwrap(), "a");
3311 }
3312
3313 #[test]
3314 fn test_cycle_zero() {
3315 let runtime = setup_runtime();
3316 let data = json!([1, 2, 3]);
3317 let expr = runtime.compile("cycle(@, `0`)").unwrap();
3318 let result = expr.search(&data).unwrap();
3319 let arr = result.as_array().unwrap();
3320 assert_eq!(arr.len(), 0);
3321 }
3322
3323 #[test]
3324 fn test_cycle_empty_array() {
3325 let runtime = setup_runtime();
3326 let data = json!([]);
3327 let expr = runtime.compile("cycle(@, `5`)").unwrap();
3328 let result = expr.search(&data).unwrap();
3329 let arr = result.as_array().unwrap();
3330 assert_eq!(arr.len(), 0);
3331 }
3332
3333 #[test]
3334 fn test_cycle_once() {
3335 let runtime = setup_runtime();
3336 let data = json!([1, 2]);
3337 let expr = runtime.compile("cycle(@, `1`)").unwrap();
3338 let result = expr.search(&data).unwrap();
3339 let arr = result.as_array().unwrap();
3340 assert_eq!(arr.len(), 2);
3341 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3342 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
3343 }
3344
3345 #[test]
3346 fn test_lag_by_one() {
3347 let runtime = setup_runtime();
3348 let data = json!([1, 2, 3]);
3349 let expr = runtime.compile("lag(@, `1`)").unwrap();
3350 let result = expr.search(&data).unwrap();
3351 assert_eq!(result, json!([null, 1, 2]));
3352 }
3353
3354 #[test]
3355 fn test_lag_by_two() {
3356 let runtime = setup_runtime();
3357 let data = json!([1, 2, 3]);
3358 let expr = runtime.compile("lag(@, `2`)").unwrap();
3359 let result = expr.search(&data).unwrap();
3360 assert_eq!(result, json!([null, null, 1]));
3361 }
3362
3363 #[test]
3364 fn test_lag_by_zero() {
3365 let runtime = setup_runtime();
3366 let data = json!([1, 2, 3]);
3367 let expr = runtime.compile("lag(@, `0`)").unwrap();
3368 let result = expr.search(&data).unwrap();
3369 assert_eq!(result, json!([1, 2, 3]));
3370 }
3371
3372 #[test]
3373 fn test_lag_exceeds_length() {
3374 let runtime = setup_runtime();
3375 let data = json!([1, 2, 3]);
3376 let expr = runtime.compile("lag(@, `5`)").unwrap();
3377 let result = expr.search(&data).unwrap();
3378 assert_eq!(result, json!([null, null, null]));
3379 }
3380
3381 #[test]
3382 fn test_lag_empty_array() {
3383 let runtime = setup_runtime();
3384 let data = json!([]);
3385 let expr = runtime.compile("lag(@, `1`)").unwrap();
3386 let result = expr.search(&data).unwrap();
3387 assert_eq!(result, json!([]));
3388 }
3389
3390 #[test]
3391 fn test_lead_by_one() {
3392 let runtime = setup_runtime();
3393 let data = json!([1, 2, 3]);
3394 let expr = runtime.compile("lead(@, `1`)").unwrap();
3395 let result = expr.search(&data).unwrap();
3396 assert_eq!(result, json!([2, 3, null]));
3397 }
3398
3399 #[test]
3400 fn test_lead_by_two() {
3401 let runtime = setup_runtime();
3402 let data = json!([1, 2, 3]);
3403 let expr = runtime.compile("lead(@, `2`)").unwrap();
3404 let result = expr.search(&data).unwrap();
3405 assert_eq!(result, json!([3, null, null]));
3406 }
3407
3408 #[test]
3409 fn test_lead_by_zero() {
3410 let runtime = setup_runtime();
3411 let data = json!([1, 2, 3]);
3412 let expr = runtime.compile("lead(@, `0`)").unwrap();
3413 let result = expr.search(&data).unwrap();
3414 assert_eq!(result, json!([1, 2, 3]));
3415 }
3416
3417 #[test]
3418 fn test_lead_exceeds_length() {
3419 let runtime = setup_runtime();
3420 let data = json!([1, 2, 3]);
3421 let expr = runtime.compile("lead(@, `5`)").unwrap();
3422 let result = expr.search(&data).unwrap();
3423 assert_eq!(result, json!([null, null, null]));
3424 }
3425
3426 #[test]
3427 fn test_lead_empty_array() {
3428 let runtime = setup_runtime();
3429 let data = json!([]);
3430 let expr = runtime.compile("lead(@, `1`)").unwrap();
3431 let result = expr.search(&data).unwrap();
3432 assert_eq!(result, json!([]));
3433 }
3434}