1use std::collections::HashSet;
4
5use serde_json::{Number, Value};
6
7use crate::functions::{Function, custom_error};
8use crate::interpreter::SearchResult;
9use crate::registry::register_if_enabled;
10use crate::{Context, Runtime, arg, defn};
11
12pub fn register_filtered(runtime: &mut Runtime, enabled: &HashSet<&str>) {
14 register_if_enabled(runtime, "unique", enabled, Box::new(UniqueFn::new()));
15 register_if_enabled(runtime, "zip", enabled, Box::new(ZipFn::new()));
16 register_if_enabled(runtime, "chunk", enabled, Box::new(ChunkFn::new()));
17 register_if_enabled(runtime, "take", enabled, Box::new(TakeFn::new()));
18 register_if_enabled(runtime, "drop", enabled, Box::new(DropFn::new()));
19 register_if_enabled(
20 runtime,
21 "flatten_deep",
22 enabled,
23 Box::new(FlattenDeepFn::new()),
24 );
25 register_if_enabled(runtime, "flatten", enabled, Box::new(FlattenFn::new()));
26 register_if_enabled(runtime, "compact", enabled, Box::new(CompactFn::new()));
27 register_if_enabled(runtime, "range", enabled, Box::new(RangeFn::new()));
28 register_if_enabled(runtime, "index_at", enabled, Box::new(IndexAtFn::new()));
29 register_if_enabled(runtime, "includes", enabled, Box::new(IncludesFn::new()));
30 register_if_enabled(runtime, "find_index", enabled, Box::new(FindIndexFn::new()));
31 register_if_enabled(runtime, "first", enabled, Box::new(FirstFn::new()));
32 register_if_enabled(runtime, "last", enabled, Box::new(LastFn::new()));
33 register_if_enabled(runtime, "group_by", enabled, Box::new(GroupByFn::new()));
34 register_if_enabled(runtime, "index_by", enabled, Box::new(IndexByFn::new()));
35 register_if_enabled(runtime, "nth", enabled, Box::new(NthFn::new()));
36 register_if_enabled(
37 runtime,
38 "interleave",
39 enabled,
40 Box::new(InterleaveFn::new()),
41 );
42 register_if_enabled(runtime, "rotate", enabled, Box::new(RotateFn::new()));
43 register_if_enabled(runtime, "partition", enabled, Box::new(PartitionFn::new()));
44 register_if_enabled(
45 runtime,
46 "difference",
47 enabled,
48 Box::new(DifferenceFn::new()),
49 );
50 register_if_enabled(
51 runtime,
52 "intersection",
53 enabled,
54 Box::new(IntersectionFn::new()),
55 );
56 register_if_enabled(runtime, "union", enabled, Box::new(UnionFn::new()));
57 register_if_enabled(
58 runtime,
59 "frequencies",
60 enabled,
61 Box::new(FrequenciesFn::new()),
62 );
63 register_if_enabled(runtime, "mode", enabled, Box::new(ModeFn::new()));
64 register_if_enabled(runtime, "cartesian", enabled, Box::new(CartesianFn::new()));
65 register_if_enabled(runtime, "initial", enabled, Box::new(InitialFn::new()));
66 register_if_enabled(runtime, "butlast", enabled, Box::new(InitialFn::new()));
68 register_if_enabled(runtime, "interpose", enabled, Box::new(InterposeFn::new()));
70 register_if_enabled(runtime, "zipmap", enabled, Box::new(ZipmapFn::new()));
71 register_if_enabled(
72 runtime,
73 "partition_by",
74 enabled,
75 Box::new(PartitionByFn::new()),
76 );
77 register_if_enabled(runtime, "dedupe", enabled, Box::new(DedupeFn::new()));
78 register_if_enabled(runtime, "tail", enabled, Box::new(TailFn::new()));
79 register_if_enabled(runtime, "without", enabled, Box::new(WithoutFn::new()));
80 register_if_enabled(runtime, "xor", enabled, Box::new(XorFn::new()));
81 register_if_enabled(runtime, "fill", enabled, Box::new(FillFn::new()));
82 register_if_enabled(runtime, "pull_at", enabled, Box::new(PullAtFn::new()));
83 register_if_enabled(runtime, "window", enabled, Box::new(WindowFn::new()));
84 register_if_enabled(
85 runtime,
86 "combinations",
87 enabled,
88 Box::new(CombinationsFn::new()),
89 );
90 register_if_enabled(runtime, "transpose", enabled, Box::new(TransposeFn::new()));
91 register_if_enabled(runtime, "pairwise", enabled, Box::new(PairwiseFn::new()));
92 register_if_enabled(
94 runtime,
95 "sliding_window",
96 enabled,
97 Box::new(WindowFn::new()),
98 );
99 register_if_enabled(
101 runtime,
102 "indices_array",
103 enabled,
104 Box::new(IndicesArrayFn::new()),
105 );
106 register_if_enabled(
107 runtime,
108 "inside_array",
109 enabled,
110 Box::new(InsideArrayFn::new()),
111 );
112 register_if_enabled(runtime, "bsearch", enabled, Box::new(BsearchFn::new()));
113 register_if_enabled(
115 runtime,
116 "repeat_array",
117 enabled,
118 Box::new(RepeatArrayFn::new()),
119 );
120 register_if_enabled(runtime, "cycle", enabled, Box::new(CycleFn::new()));
121}
122
123defn!(UniqueFn, vec![arg!(array)], None);
128
129impl Function for UniqueFn {
130 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
131 self.signature.validate(args, ctx)?;
132
133 let arr = args[0]
134 .as_array()
135 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
136
137 let mut seen = HashSet::new();
138 let mut result = Vec::new();
139
140 for item in arr {
141 let key = serde_json::to_string(item).unwrap_or_default();
142 if seen.insert(key) {
143 result.push(item.clone());
144 }
145 }
146
147 Ok(Value::Array(result))
148 }
149}
150
151defn!(ZipFn, vec![arg!(array), arg!(array)], None);
156
157impl Function for ZipFn {
158 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
159 self.signature.validate(args, ctx)?;
160
161 let arr1 = args[0]
162 .as_array()
163 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
164
165 let arr2 = args[1]
166 .as_array()
167 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
168
169 let result: Vec<Value> = arr1
170 .iter()
171 .zip(arr2.iter())
172 .map(|(a, b)| Value::Array(vec![a.clone(), b.clone()]))
173 .collect();
174
175 Ok(Value::Array(result))
176 }
177}
178
179defn!(ChunkFn, vec![arg!(array), arg!(number)], None);
184
185impl Function for ChunkFn {
186 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
187 self.signature.validate(args, ctx)?;
188
189 let arr = args[0]
190 .as_array()
191 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
192
193 let size = args[1]
194 .as_f64()
195 .map(|n| n as usize)
196 .ok_or_else(|| custom_error(ctx, "Expected positive number for size"))?;
197
198 if size == 0 {
199 return Ok(Value::Array(vec![]));
200 }
201
202 let chunks: Vec<Value> = arr
203 .chunks(size)
204 .map(|chunk| Value::Array(chunk.to_vec()))
205 .collect();
206
207 Ok(Value::Array(chunks))
208 }
209}
210
211defn!(TakeFn, vec![arg!(array), arg!(number)], None);
216
217impl Function for TakeFn {
218 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
219 self.signature.validate(args, ctx)?;
220
221 let arr = args[0]
222 .as_array()
223 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
224
225 let n = args[1]
226 .as_f64()
227 .map(|n| n as usize)
228 .ok_or_else(|| custom_error(ctx, "Expected positive number"))?;
229
230 let result: Vec<Value> = arr.iter().take(n).cloned().collect();
231
232 Ok(Value::Array(result))
233 }
234}
235
236defn!(DropFn, vec![arg!(array), arg!(number)], None);
241
242impl Function for DropFn {
243 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
244 self.signature.validate(args, ctx)?;
245
246 let arr = args[0]
247 .as_array()
248 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
249
250 let n = args[1]
251 .as_f64()
252 .map(|n| n as usize)
253 .ok_or_else(|| custom_error(ctx, "Expected positive number"))?;
254
255 let result: Vec<Value> = arr.iter().skip(n).cloned().collect();
256
257 Ok(Value::Array(result))
258 }
259}
260
261defn!(FlattenDeepFn, vec![arg!(array)], None);
266
267fn flatten_recursive(arr: &[Value]) -> Vec<Value> {
268 let mut result = Vec::new();
269 for item in arr {
270 if let Some(inner) = item.as_array() {
271 result.extend(flatten_recursive(inner));
272 } else {
273 result.push(item.clone());
274 }
275 }
276 result
277}
278
279impl Function for FlattenDeepFn {
280 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
281 self.signature.validate(args, ctx)?;
282
283 let arr = args[0]
284 .as_array()
285 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
286
287 Ok(Value::Array(flatten_recursive(arr)))
288 }
289}
290
291defn!(FlattenFn, vec![arg!(array)], None);
296
297impl Function for FlattenFn {
298 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
299 self.signature.validate(args, ctx)?;
300
301 let arr = args[0]
302 .as_array()
303 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
304
305 let mut result = Vec::new();
306 for item in arr {
307 if let Some(inner) = item.as_array() {
308 result.extend(inner.iter().cloned());
309 } else {
310 result.push(item.clone());
311 }
312 }
313
314 Ok(Value::Array(result))
315 }
316}
317
318defn!(CompactFn, vec![arg!(array)], None);
323
324impl Function for CompactFn {
325 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
326 self.signature.validate(args, ctx)?;
327
328 let arr = args[0]
329 .as_array()
330 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
331
332 let result: Vec<Value> = arr
333 .iter()
334 .filter(|v| !v.is_null() && !matches!(v, Value::Bool(false)))
335 .cloned()
336 .collect();
337
338 Ok(Value::Array(result))
339 }
340}
341
342defn!(
347 RangeFn,
348 vec![arg!(number), arg!(number)],
349 Some(arg!(number))
350);
351
352impl Function for RangeFn {
353 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
354 self.signature.validate(args, ctx)?;
355
356 let start = args[0]
357 .as_f64()
358 .map(|n| n as i64)
359 .ok_or_else(|| custom_error(ctx, "Expected start number"))?;
360
361 let end = args[1]
362 .as_f64()
363 .map(|n| n as i64)
364 .ok_or_else(|| custom_error(ctx, "Expected end number"))?;
365
366 let step = if args.len() > 2 {
367 args[2]
368 .as_f64()
369 .map(|n| n as i64)
370 .ok_or_else(|| custom_error(ctx, "Expected step number"))?
371 } else {
372 1
373 };
374
375 if step == 0 {
376 return Err(custom_error(ctx, "Step cannot be zero"));
377 }
378
379 let mut result = Vec::new();
380 let mut current = start;
381
382 const MAX_RANGE: usize = 10000;
383
384 if step > 0 {
385 while current < end && result.len() < MAX_RANGE {
386 result.push(Value::Number(Number::from(current)));
387 current += step;
388 }
389 } else {
390 while current > end && result.len() < MAX_RANGE {
391 result.push(Value::Number(Number::from(current)));
392 current += step;
393 }
394 }
395
396 Ok(Value::Array(result))
397 }
398}
399
400defn!(IndexAtFn, vec![arg!(array), arg!(number)], None);
405
406impl Function for IndexAtFn {
407 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
408 self.signature.validate(args, ctx)?;
409
410 let arr = args[0]
411 .as_array()
412 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
413
414 let index = args[1]
415 .as_f64()
416 .map(|n| n as i64)
417 .ok_or_else(|| custom_error(ctx, "Expected number for index"))?;
418
419 let len = arr.len() as i64;
420 let actual_index = if index < 0 {
421 (len + index) as usize
422 } else {
423 index as usize
424 };
425
426 if actual_index < arr.len() {
427 Ok(arr[actual_index].clone())
428 } else {
429 Ok(Value::Null)
430 }
431 }
432}
433
434defn!(IncludesFn, vec![arg!(array), arg!(any)], None);
439
440impl Function for IncludesFn {
441 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
442 self.signature.validate(args, ctx)?;
443
444 let arr = args[0]
445 .as_array()
446 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
447
448 let search_key = serde_json::to_string(&args[1]).unwrap_or_default();
449
450 let found = arr.iter().any(|item| {
451 let item_key = serde_json::to_string(item).unwrap_or_default();
452 item_key == search_key
453 });
454
455 Ok(Value::Bool(found))
456 }
457}
458
459defn!(FindIndexFn, vec![arg!(array), arg!(any)], None);
464
465impl Function for FindIndexFn {
466 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
467 self.signature.validate(args, ctx)?;
468
469 let arr = args[0]
470 .as_array()
471 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
472
473 let search_key = serde_json::to_string(&args[1]).unwrap_or_default();
474
475 let index = arr
476 .iter()
477 .position(|item| {
478 let item_key = serde_json::to_string(item).unwrap_or_default();
479 item_key == search_key
480 })
481 .map(|i| i as i64)
482 .unwrap_or(-1);
483
484 Ok(Value::Number(Number::from(index)))
485 }
486}
487
488defn!(FirstFn, vec![arg!(array)], None);
493
494impl Function for FirstFn {
495 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
496 self.signature.validate(args, ctx)?;
497
498 let arr = args[0]
499 .as_array()
500 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
501
502 Ok(arr.first().cloned().unwrap_or(Value::Null))
503 }
504}
505
506defn!(LastFn, vec![arg!(array)], None);
511
512impl Function for LastFn {
513 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
514 self.signature.validate(args, ctx)?;
515
516 let arr = args[0]
517 .as_array()
518 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
519
520 Ok(arr.last().cloned().unwrap_or(Value::Null))
521 }
522}
523
524defn!(GroupByFn, vec![arg!(array), arg!(string)], None);
529
530impl Function for GroupByFn {
531 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
532 self.signature.validate(args, ctx)?;
533
534 let arr = args[0]
535 .as_array()
536 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
537
538 let field_name = args[1]
539 .as_str()
540 .ok_or_else(|| custom_error(ctx, "Expected field name string"))?;
541
542 let mut groups: std::collections::BTreeMap<String, Vec<Value>> =
543 std::collections::BTreeMap::new();
544
545 for item in arr {
546 let key = if let Some(obj) = item.as_object() {
547 if let Some(field_value) = obj.get(field_name) {
548 match field_value {
549 Value::String(s) => s.clone(),
550 Value::Number(n) => n.to_string(),
551 Value::Bool(b) => b.to_string(),
552 Value::Null => "null".to_string(),
553 _ => continue,
554 }
555 } else {
556 "null".to_string()
557 }
558 } else {
559 continue;
560 };
561 groups.entry(key).or_default().push(item.clone());
562 }
563
564 let mut result = serde_json::Map::new();
565 for (k, v) in groups {
566 result.insert(k, Value::Array(v));
567 }
568
569 Ok(Value::Object(result))
570 }
571}
572
573defn!(IndexByFn, vec![arg!(array), arg!(string)], None);
578
579impl Function for IndexByFn {
580 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
581 self.signature.validate(args, ctx)?;
582
583 let arr = args[0]
584 .as_array()
585 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
586
587 let field_name = args[1]
588 .as_str()
589 .ok_or_else(|| custom_error(ctx, "Expected field name string"))?;
590
591 let mut result = serde_json::Map::new();
592
593 for item in arr {
594 let key = if let Some(obj) = item.as_object() {
595 if let Some(field_value) = obj.get(field_name) {
596 match field_value {
597 Value::String(s) => s.clone(),
598 Value::Number(n) => n.to_string(),
599 Value::Bool(b) => b.to_string(),
600 Value::Null => "null".to_string(),
601 _ => continue,
602 }
603 } else {
604 continue;
606 }
607 } else {
608 continue;
609 };
610 result.insert(key, item.clone());
612 }
613
614 Ok(Value::Object(result))
615 }
616}
617
618defn!(NthFn, vec![arg!(array), arg!(number)], None);
623
624impl Function for NthFn {
625 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
626 self.signature.validate(args, ctx)?;
627
628 let arr = args[0]
629 .as_array()
630 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
631
632 let n = args[1]
633 .as_f64()
634 .ok_or_else(|| custom_error(ctx, "Expected number argument"))? as usize;
635
636 if n == 0 {
637 return Ok(Value::Null);
638 }
639
640 let result: Vec<Value> = arr.iter().step_by(n).cloned().collect();
641 Ok(Value::Array(result))
642 }
643}
644
645defn!(InterleaveFn, vec![arg!(array), arg!(array)], None);
650
651impl Function for InterleaveFn {
652 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
653 self.signature.validate(args, ctx)?;
654
655 let arr1 = args[0]
656 .as_array()
657 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
658
659 let arr2 = args[1]
660 .as_array()
661 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
662
663 let mut result = Vec::with_capacity(arr1.len() + arr2.len());
664 let mut iter1 = arr1.iter();
665 let mut iter2 = arr2.iter();
666
667 loop {
668 match (iter1.next(), iter2.next()) {
669 (Some(a), Some(b)) => {
670 result.push(a.clone());
671 result.push(b.clone());
672 }
673 (Some(a), None) => {
674 result.push(a.clone());
675 result.extend(iter1.cloned());
676 break;
677 }
678 (None, Some(b)) => {
679 result.push(b.clone());
680 result.extend(iter2.cloned());
681 break;
682 }
683 (None, None) => break,
684 }
685 }
686
687 Ok(Value::Array(result))
688 }
689}
690
691defn!(RotateFn, vec![arg!(array), arg!(number)], None);
696
697impl Function for RotateFn {
698 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
699 self.signature.validate(args, ctx)?;
700
701 let arr = args[0]
702 .as_array()
703 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
704
705 if arr.is_empty() {
706 return Ok(Value::Array(vec![]));
707 }
708
709 let n = args[1]
710 .as_f64()
711 .ok_or_else(|| custom_error(ctx, "Expected number argument"))? as i64;
712
713 let len = arr.len() as i64;
714 let rotation = ((n % len) + len) % len;
715 let rotation = rotation as usize;
716
717 let mut result = Vec::with_capacity(arr.len());
718 result.extend(arr[rotation..].iter().cloned());
719 result.extend(arr[..rotation].iter().cloned());
720
721 Ok(Value::Array(result))
722 }
723}
724
725defn!(PartitionFn, vec![arg!(array), arg!(number)], None);
730
731impl Function for PartitionFn {
732 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
733 self.signature.validate(args, ctx)?;
734
735 let arr = args[0]
736 .as_array()
737 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
738
739 let n = args[1]
740 .as_f64()
741 .ok_or_else(|| custom_error(ctx, "Expected number argument"))? as usize;
742
743 if n == 0 {
744 return Ok(Value::Null);
745 }
746
747 let len = arr.len();
748 let base_size = len / n;
749 let remainder = len % n;
750
751 let mut result = Vec::with_capacity(n);
752 let mut start = 0;
753
754 for i in 0..n {
755 let size = base_size + if i < remainder { 1 } else { 0 };
756 if size > 0 {
757 result.push(Value::Array(arr[start..start + size].to_vec()));
758 } else {
759 result.push(Value::Array(vec![]));
760 }
761 start += size;
762 }
763
764 Ok(Value::Array(result))
765 }
766}
767
768defn!(DifferenceFn, vec![arg!(array), arg!(array)], None);
773
774impl Function for DifferenceFn {
775 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
776 self.signature.validate(args, ctx)?;
777
778 let arr1 = args[0]
779 .as_array()
780 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
781
782 let arr2 = args[1]
783 .as_array()
784 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
785
786 let set2: HashSet<String> = arr2
787 .iter()
788 .map(|v| serde_json::to_string(v).unwrap_or_default())
789 .collect();
790
791 let result: Vec<Value> = arr1
792 .iter()
793 .filter(|v| {
794 let key = serde_json::to_string(*v).unwrap_or_default();
795 !set2.contains(&key)
796 })
797 .cloned()
798 .collect();
799
800 Ok(Value::Array(result))
801 }
802}
803
804defn!(IntersectionFn, vec![arg!(array), arg!(array)], None);
809
810impl Function for IntersectionFn {
811 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
812 self.signature.validate(args, ctx)?;
813
814 let arr1 = args[0]
815 .as_array()
816 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
817
818 let arr2 = args[1]
819 .as_array()
820 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
821
822 let set2: HashSet<String> = arr2
823 .iter()
824 .map(|v| serde_json::to_string(v).unwrap_or_default())
825 .collect();
826
827 let mut seen: HashSet<String> = HashSet::new();
828 let result: Vec<Value> = arr1
829 .iter()
830 .filter(|v| {
831 let key = serde_json::to_string(*v).unwrap_or_default();
832 set2.contains(&key) && seen.insert(key)
833 })
834 .cloned()
835 .collect();
836
837 Ok(Value::Array(result))
838 }
839}
840
841defn!(UnionFn, vec![arg!(array), arg!(array)], None);
846
847impl Function for UnionFn {
848 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
849 self.signature.validate(args, ctx)?;
850
851 let arr1 = args[0]
852 .as_array()
853 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
854
855 let arr2 = args[1]
856 .as_array()
857 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
858
859 let mut seen: HashSet<String> = HashSet::new();
860 let mut result: Vec<Value> = Vec::new();
861
862 for item in arr1.iter().chain(arr2.iter()) {
863 let key = serde_json::to_string(item).unwrap_or_default();
864 if seen.insert(key) {
865 result.push(item.clone());
866 }
867 }
868
869 Ok(Value::Array(result))
870 }
871}
872
873defn!(FrequenciesFn, vec![arg!(array)], None);
878
879impl Function for FrequenciesFn {
880 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
881 self.signature.validate(args, ctx)?;
882
883 let arr = args[0]
884 .as_array()
885 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
886
887 let mut counts: std::collections::HashMap<String, i64> = std::collections::HashMap::new();
888
889 for item in arr {
890 let key = match item {
891 Value::String(s) => s.clone(),
892 Value::Number(n) => n.to_string(),
893 Value::Bool(b) => b.to_string(),
894 Value::Null => "null".to_string(),
895 _ => serde_json::to_string(item).unwrap_or_else(|_| "null".to_string()),
896 };
897 *counts.entry(key).or_insert(0) += 1;
898 }
899
900 let mut result = serde_json::Map::new();
901 let sorted: std::collections::BTreeMap<String, i64> = counts.into_iter().collect();
903 for (k, v) in sorted {
904 result.insert(k, Value::Number(Number::from(v)));
905 }
906
907 Ok(Value::Object(result))
908 }
909}
910
911defn!(ModeFn, vec![arg!(array)], None);
916
917impl Function for ModeFn {
918 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
919 self.signature.validate(args, ctx)?;
920
921 let arr = args[0]
922 .as_array()
923 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
924
925 if arr.is_empty() {
926 return Ok(Value::Null);
927 }
928
929 let mut counts: std::collections::HashMap<String, (i64, Value)> =
930 std::collections::HashMap::new();
931
932 for item in arr {
933 let key = serde_json::to_string(item).unwrap_or_default();
934 counts
935 .entry(key)
936 .and_modify(|(count, _)| *count += 1)
937 .or_insert((1, item.clone()));
938 }
939
940 let (_, (_, mode_value)) = counts
941 .into_iter()
942 .max_by_key(|(_, (count, _))| *count)
943 .unwrap();
944
945 Ok(mode_value)
946 }
947}
948
949defn!(CartesianFn, vec![arg!(array)], Some(arg!(array)));
955
956impl Function for CartesianFn {
957 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
958 self.signature.validate(args, ctx)?;
959
960 let first = args[0]
961 .as_array()
962 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
963
964 if args.len() == 2 {
969 let arr2 = args[1]
971 .as_array()
972 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
973
974 let mut result = Vec::with_capacity(first.len() * arr2.len());
975 for a in first {
976 for b in arr2 {
977 result.push(Value::Array(vec![a.clone(), b.clone()]));
978 }
979 }
980 Ok(Value::Array(result))
981 } else {
982 let arrays: Vec<&Vec<Value>> =
985 first.iter().filter_map(|item| item.as_array()).collect();
986
987 if arrays.len() != first.len() || arrays.is_empty() {
988 return Ok(Value::Array(vec![]));
990 }
991
992 let result = cartesian_product_n(&arrays);
994 Ok(Value::Array(result))
995 }
996 }
997}
998
999fn cartesian_product_n(arrays: &[&Vec<Value>]) -> Vec<Value> {
1001 if arrays.is_empty() {
1002 return vec![];
1003 }
1004
1005 if arrays.len() == 1 {
1006 return arrays[0]
1008 .iter()
1009 .map(|item| Value::Array(vec![item.clone()]))
1010 .collect();
1011 }
1012
1013 let total_size: usize = arrays.iter().map(|a| a.len()).product();
1015 if total_size == 0 {
1016 return vec![];
1017 }
1018
1019 let mut result = Vec::with_capacity(total_size);
1020
1021 let mut indices = vec![0usize; arrays.len()];
1023
1024 loop {
1025 let combo: Vec<Value> = indices
1027 .iter()
1028 .enumerate()
1029 .map(|(arr_idx, &elem_idx)| arrays[arr_idx][elem_idx].clone())
1030 .collect();
1031 result.push(Value::Array(combo));
1032
1033 let mut carry = true;
1035 for i in (0..arrays.len()).rev() {
1036 if carry {
1037 indices[i] += 1;
1038 if indices[i] >= arrays[i].len() {
1039 indices[i] = 0;
1040 } else {
1041 carry = false;
1042 }
1043 }
1044 }
1045
1046 if carry {
1048 break;
1049 }
1050 }
1051
1052 result
1053}
1054
1055defn!(InitialFn, vec![arg!(array)], None);
1060
1061impl Function for InitialFn {
1062 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1063 self.signature.validate(args, ctx)?;
1064
1065 let arr = args[0]
1066 .as_array()
1067 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1068
1069 if arr.is_empty() {
1070 return Ok(Value::Array(vec![]));
1071 }
1072
1073 let result: Vec<Value> = arr[..arr.len() - 1].to_vec();
1074 Ok(Value::Array(result))
1075 }
1076}
1077
1078defn!(InterposeFn, vec![arg!(array), arg!(any)], None);
1083
1084impl Function for InterposeFn {
1085 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1086 self.signature.validate(args, ctx)?;
1087
1088 let arr = args[0]
1089 .as_array()
1090 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1091
1092 let separator = args[1].clone();
1093
1094 if arr.is_empty() {
1095 return Ok(Value::Array(vec![]));
1096 }
1097
1098 if arr.len() == 1 {
1099 return Ok(Value::Array(arr.clone()));
1100 }
1101
1102 let mut result = Vec::with_capacity(arr.len() * 2 - 1);
1103 for (i, item) in arr.iter().enumerate() {
1104 if i > 0 {
1105 result.push(separator.clone());
1106 }
1107 result.push(item.clone());
1108 }
1109
1110 Ok(Value::Array(result))
1111 }
1112}
1113
1114defn!(ZipmapFn, vec![arg!(array), arg!(array)], None);
1119
1120impl Function for ZipmapFn {
1121 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1122 self.signature.validate(args, ctx)?;
1123
1124 let keys = args[0]
1125 .as_array()
1126 .ok_or_else(|| custom_error(ctx, "Expected array argument for keys"))?;
1127
1128 let values = args[1]
1129 .as_array()
1130 .ok_or_else(|| custom_error(ctx, "Expected array argument for values"))?;
1131
1132 let len = keys.len().min(values.len());
1133 let mut result = serde_json::Map::new();
1134
1135 for i in 0..len {
1136 let key = keys[i]
1137 .as_str()
1138 .ok_or_else(|| custom_error(ctx, "Keys must be strings"))?;
1139 result.insert(key.to_string(), values[i].clone());
1140 }
1141
1142 Ok(Value::Object(result))
1143 }
1144}
1145
1146defn!(PartitionByFn, vec![arg!(array), arg!(string)], None);
1151
1152impl Function for PartitionByFn {
1153 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1154 self.signature.validate(args, ctx)?;
1155
1156 let arr = args[0]
1157 .as_array()
1158 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1159
1160 let field_name = args[1]
1161 .as_str()
1162 .ok_or_else(|| custom_error(ctx, "Expected field name string"))?;
1163
1164 if arr.is_empty() {
1165 return Ok(Value::Array(vec![]));
1166 }
1167
1168 let mut result: Vec<Value> = Vec::new();
1169 let mut current_partition: Vec<Value> = Vec::new();
1170 let mut last_key: Option<String> = None;
1171
1172 for item in arr {
1173 let key = if let Some(obj) = item.as_object() {
1175 if let Some(field_value) = obj.get(field_name) {
1176 serde_json::to_string(field_value).unwrap_or_default()
1177 } else {
1178 "null".to_string()
1179 }
1180 } else {
1181 serde_json::to_string(item).unwrap_or_default()
1183 };
1184
1185 match &last_key {
1186 Some(prev_key) if *prev_key == key => {
1187 current_partition.push(item.clone());
1188 }
1189 _ => {
1190 if !current_partition.is_empty() {
1191 result.push(Value::Array(current_partition));
1192 }
1193 current_partition = vec![item.clone()];
1194 last_key = Some(key);
1195 }
1196 }
1197 }
1198
1199 if !current_partition.is_empty() {
1201 result.push(Value::Array(current_partition));
1202 }
1203
1204 Ok(Value::Array(result))
1205 }
1206}
1207
1208defn!(DedupeFn, vec![arg!(array)], None);
1213
1214impl Function for DedupeFn {
1215 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1216 self.signature.validate(args, ctx)?;
1217
1218 let arr = args[0]
1219 .as_array()
1220 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1221
1222 if arr.is_empty() {
1223 return Ok(Value::Array(vec![]));
1224 }
1225
1226 let mut result: Vec<Value> = Vec::with_capacity(arr.len());
1227 let mut last_key: Option<String> = None;
1228
1229 for item in arr {
1230 let key = serde_json::to_string(item).unwrap_or_default();
1231 match &last_key {
1232 Some(prev_key) if *prev_key == key => {
1233 }
1235 _ => {
1236 result.push(item.clone());
1237 last_key = Some(key);
1238 }
1239 }
1240 }
1241
1242 Ok(Value::Array(result))
1243 }
1244}
1245
1246defn!(TailFn, vec![arg!(array)], None);
1251
1252impl Function for TailFn {
1253 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1254 self.signature.validate(args, ctx)?;
1255
1256 let arr = args[0]
1257 .as_array()
1258 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1259
1260 if arr.is_empty() {
1261 return Ok(Value::Array(vec![]));
1262 }
1263
1264 let result: Vec<Value> = arr[1..].to_vec();
1265 Ok(Value::Array(result))
1266 }
1267}
1268
1269defn!(WithoutFn, vec![arg!(array), arg!(array)], None);
1274
1275impl Function for WithoutFn {
1276 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1277 self.signature.validate(args, ctx)?;
1278
1279 let arr = args[0]
1280 .as_array()
1281 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1282
1283 let exclude = args[1]
1284 .as_array()
1285 .ok_or_else(|| custom_error(ctx, "Expected array argument for values to exclude"))?;
1286
1287 let exclude_set: HashSet<String> = exclude
1289 .iter()
1290 .map(|v| serde_json::to_string(v).unwrap_or_default())
1291 .collect();
1292
1293 let result: Vec<Value> = arr
1294 .iter()
1295 .filter(|item| {
1296 let key = serde_json::to_string(*item).unwrap_or_default();
1297 !exclude_set.contains(&key)
1298 })
1299 .cloned()
1300 .collect();
1301
1302 Ok(Value::Array(result))
1303 }
1304}
1305
1306defn!(XorFn, vec![arg!(array), arg!(array)], None);
1311
1312impl Function for XorFn {
1313 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1314 self.signature.validate(args, ctx)?;
1315
1316 let arr1 = args[0]
1317 .as_array()
1318 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1319
1320 let arr2 = args[1]
1321 .as_array()
1322 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1323
1324 let set1: HashSet<String> = arr1
1326 .iter()
1327 .map(|v| serde_json::to_string(v).unwrap_or_default())
1328 .collect();
1329
1330 let set2: HashSet<String> = arr2
1331 .iter()
1332 .map(|v| serde_json::to_string(v).unwrap_or_default())
1333 .collect();
1334
1335 let mut result = Vec::new();
1336
1337 for item in arr1 {
1339 let key = serde_json::to_string(item).unwrap_or_default();
1340 if !set2.contains(&key) {
1341 result.push(item.clone());
1342 }
1343 }
1344
1345 for item in arr2 {
1347 let key = serde_json::to_string(item).unwrap_or_default();
1348 if !set1.contains(&key) {
1349 result.push(item.clone());
1350 }
1351 }
1352
1353 Ok(Value::Array(result))
1354 }
1355}
1356
1357defn!(
1362 WindowFn,
1363 vec![arg!(array), arg!(number)],
1364 Some(arg!(number))
1365);
1366
1367impl Function for WindowFn {
1368 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1369 self.signature.validate(args, ctx)?;
1370
1371 let arr = args[0]
1372 .as_array()
1373 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1374
1375 let size = args[1]
1376 .as_f64()
1377 .ok_or_else(|| custom_error(ctx, "Expected number for window size"))?
1378 as usize;
1379
1380 if size == 0 {
1381 return Ok(Value::Array(vec![]));
1382 }
1383
1384 let step = if args.len() > 2 {
1386 args[2]
1387 .as_f64()
1388 .ok_or_else(|| custom_error(ctx, "Expected number for step"))? as usize
1389 } else {
1390 1
1391 };
1392
1393 if step == 0 {
1394 return Err(custom_error(ctx, "Step cannot be zero"));
1395 }
1396
1397 let len = arr.len();
1398 if len < size {
1399 return Ok(Value::Array(vec![]));
1400 }
1401
1402 let mut result = Vec::new();
1403 let mut i = 0;
1404
1405 while i + size <= len {
1406 let window: Vec<Value> = arr[i..i + size].to_vec();
1407 result.push(Value::Array(window));
1408 i += step;
1409 }
1410
1411 Ok(Value::Array(result))
1412 }
1413}
1414
1415defn!(CombinationsFn, vec![arg!(array), arg!(number)], None);
1420
1421fn generate_combinations(arr: &[Value], k: usize) -> Vec<Vec<Value>> {
1422 if k == 0 {
1423 return vec![vec![]];
1424 }
1425 if arr.len() < k {
1426 return vec![];
1427 }
1428
1429 let mut result = Vec::new();
1430
1431 let first = arr[0].clone();
1433 let rest = &arr[1..];
1434 for mut combo in generate_combinations(rest, k - 1) {
1435 let mut new_combo = vec![first.clone()];
1436 new_combo.append(&mut combo);
1437 result.push(new_combo);
1438 }
1439
1440 result.extend(generate_combinations(rest, k));
1442
1443 result
1444}
1445
1446impl Function for CombinationsFn {
1447 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1448 self.signature.validate(args, ctx)?;
1449
1450 let arr = args[0]
1451 .as_array()
1452 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1453
1454 let k = args[1]
1455 .as_f64()
1456 .ok_or_else(|| custom_error(ctx, "Expected number for k"))? as usize;
1457
1458 const MAX_COMBINATIONS: usize = 10000;
1460
1461 let n = arr.len();
1463 if n > 20 && k > 3 && k < n - 3 {
1464 return Err(custom_error(ctx, "Combination size too large"));
1465 }
1466
1467 let combinations = generate_combinations(arr, k);
1468
1469 if combinations.len() > MAX_COMBINATIONS {
1470 return Err(custom_error(ctx, "Too many combinations generated"));
1471 }
1472
1473 let result: Vec<Value> = combinations.into_iter().map(Value::Array).collect();
1474
1475 Ok(Value::Array(result))
1476 }
1477}
1478
1479defn!(FillFn, vec![arg!(array), arg!(any)], Some(arg!(number)));
1484
1485impl Function for FillFn {
1486 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1487 self.signature.validate(args, ctx)?;
1488
1489 let arr = args[0]
1490 .as_array()
1491 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1492
1493 let fill_value = args[1].clone();
1494
1495 let len = arr.len();
1496 if len == 0 {
1497 return Ok(Value::Array(vec![]));
1498 }
1499
1500 let start = if args.len() > 2 {
1502 let s = args[2]
1503 .as_f64()
1504 .ok_or_else(|| custom_error(ctx, "Expected number for start index"))?
1505 as i64;
1506 if s < 0 {
1508 (len as i64 + s).max(0) as usize
1509 } else {
1510 (s as usize).min(len)
1511 }
1512 } else {
1513 0
1514 };
1515
1516 let end = if args.len() > 3 {
1517 let e = args[3]
1518 .as_f64()
1519 .ok_or_else(|| custom_error(ctx, "Expected number for end index"))?
1520 as i64;
1521 if e < 0 {
1523 (len as i64 + e).max(0) as usize
1524 } else {
1525 (e as usize).min(len)
1526 }
1527 } else {
1528 len
1529 };
1530
1531 let mut result: Vec<Value> = arr.clone();
1532
1533 for item in result.iter_mut().take(end.min(len)).skip(start) {
1534 *item = fill_value.clone();
1535 }
1536
1537 Ok(Value::Array(result))
1538 }
1539}
1540
1541defn!(PullAtFn, vec![arg!(array), arg!(array)], None);
1546
1547impl Function for PullAtFn {
1548 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1549 self.signature.validate(args, ctx)?;
1550
1551 let arr = args[0]
1552 .as_array()
1553 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1554
1555 let indices = args[1]
1556 .as_array()
1557 .ok_or_else(|| custom_error(ctx, "Expected array of indices"))?;
1558
1559 let len = arr.len();
1560 let mut result = Vec::new();
1561
1562 for idx_var in indices {
1563 let idx = idx_var
1564 .as_f64()
1565 .ok_or_else(|| custom_error(ctx, "Expected number in indices array"))?
1566 as i64;
1567
1568 let actual_idx = if idx < 0 {
1570 (len as i64 + idx).max(0) as usize
1571 } else {
1572 idx as usize
1573 };
1574
1575 if actual_idx < len {
1576 result.push(arr[actual_idx].clone());
1577 }
1578 }
1579
1580 Ok(Value::Array(result))
1581 }
1582}
1583
1584defn!(TransposeFn, vec![arg!(array)], None);
1589
1590impl Function for TransposeFn {
1591 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1592 self.signature.validate(args, ctx)?;
1593
1594 let arr = args[0]
1595 .as_array()
1596 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1597
1598 if arr.is_empty() {
1599 return Ok(Value::Array(vec![]));
1600 }
1601
1602 let mut inner_arrays: Vec<&Vec<Value>> = Vec::new();
1604 let mut min_len = usize::MAX;
1605
1606 for item in arr {
1607 if let Some(inner) = item.as_array() {
1608 min_len = min_len.min(inner.len());
1609 inner_arrays.push(inner);
1610 } else {
1611 return Ok(Value::Array(vec![]));
1613 }
1614 }
1615
1616 if inner_arrays.is_empty() || min_len == 0 {
1617 return Ok(Value::Array(vec![]));
1618 }
1619
1620 let mut result = Vec::with_capacity(min_len);
1622 for i in 0..min_len {
1623 let mut row = Vec::with_capacity(inner_arrays.len());
1624 for inner in &inner_arrays {
1625 row.push(inner[i].clone());
1626 }
1627 result.push(Value::Array(row));
1628 }
1629
1630 Ok(Value::Array(result))
1631 }
1632}
1633
1634defn!(PairwiseFn, vec![arg!(array)], None);
1639
1640impl Function for PairwiseFn {
1641 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1642 self.signature.validate(args, ctx)?;
1643
1644 let arr = args[0]
1645 .as_array()
1646 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1647
1648 if arr.len() < 2 {
1649 return Ok(Value::Array(vec![]));
1650 }
1651
1652 let mut result = Vec::with_capacity(arr.len() - 1);
1653 for i in 0..arr.len() - 1 {
1654 let pair = vec![arr[i].clone(), arr[i + 1].clone()];
1655 result.push(Value::Array(pair));
1656 }
1657
1658 Ok(Value::Array(result))
1659 }
1660}
1661
1662defn!(IndicesArrayFn, vec![arg!(array), arg!(any)], None);
1667
1668impl Function for IndicesArrayFn {
1669 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1670 self.signature.validate(args, ctx)?;
1671
1672 let arr = args[0]
1673 .as_array()
1674 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1675
1676 let search_key = serde_json::to_string(&args[1]).unwrap_or_default();
1677
1678 let mut indices: Vec<Value> = Vec::new();
1679 for (i, item) in arr.iter().enumerate() {
1680 let item_key = serde_json::to_string(item).unwrap_or_default();
1681 if item_key == search_key {
1682 indices.push(Value::Number(Number::from(i as i64)));
1683 }
1684 }
1685
1686 Ok(Value::Array(indices))
1687 }
1688}
1689
1690defn!(InsideArrayFn, vec![arg!(array), arg!(array)], None);
1695
1696impl Function for InsideArrayFn {
1697 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1698 self.signature.validate(args, ctx)?;
1699
1700 let needle = args[0]
1701 .as_array()
1702 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1703
1704 let haystack = args[1]
1705 .as_array()
1706 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1707
1708 let haystack_set: HashSet<String> = haystack
1710 .iter()
1711 .map(|item| serde_json::to_string(item).unwrap_or_default())
1712 .collect();
1713
1714 let result = needle.iter().all(|item| {
1716 let item_key = serde_json::to_string(item).unwrap_or_default();
1717 haystack_set.contains(&item_key)
1718 });
1719
1720 Ok(Value::Bool(result))
1721 }
1722}
1723
1724defn!(BsearchFn, vec![arg!(array), arg!(any)], None);
1729
1730impl Function for BsearchFn {
1731 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1732 self.signature.validate(args, ctx)?;
1733
1734 let arr = args[0]
1735 .as_array()
1736 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1737
1738 let target = &args[1];
1739
1740 if arr.is_empty() {
1741 return Ok(Value::Number(Number::from(-1)));
1742 }
1743
1744 fn compare_values(a: &Value, b: &Value) -> std::cmp::Ordering {
1747 match (a, b) {
1748 (Value::Number(n1), Value::Number(n2)) => {
1750 let f1 = n1.as_f64().unwrap_or(0.0);
1751 let f2 = n2.as_f64().unwrap_or(0.0);
1752 f1.partial_cmp(&f2).unwrap_or(std::cmp::Ordering::Equal)
1753 }
1754 (Value::String(s1), Value::String(s2)) => s1.cmp(s2),
1756 (Value::Bool(b1), Value::Bool(b2)) => b1.cmp(b2),
1758 _ => {
1760 let s1 = serde_json::to_string(a).unwrap_or_default();
1761 let s2 = serde_json::to_string(b).unwrap_or_default();
1762 s1.cmp(&s2)
1763 }
1764 }
1765 }
1766
1767 let mut left = 0i64;
1768 let mut right = arr.len() as i64 - 1;
1769
1770 while left <= right {
1771 let mid = left + (right - left) / 2;
1772
1773 match compare_values(&arr[mid as usize], target) {
1774 std::cmp::Ordering::Equal => {
1775 return Ok(Value::Number(Number::from(mid)));
1776 }
1777 std::cmp::Ordering::Less => {
1778 left = mid + 1;
1779 }
1780 std::cmp::Ordering::Greater => {
1781 right = mid - 1;
1782 }
1783 }
1784 }
1785
1786 let result = -(left) - 1;
1789 Ok(Value::Number(Number::from(result)))
1790 }
1791}
1792
1793defn!(RepeatArrayFn, vec![arg!(any), arg!(number)], None);
1798
1799impl Function for RepeatArrayFn {
1800 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1801 self.signature.validate(args, ctx)?;
1802
1803 let value = &args[0];
1804 let n = args[1]
1805 .as_f64()
1806 .ok_or_else(|| custom_error(ctx, "Expected number for count argument"))?
1807 as i64;
1808
1809 if n < 0 {
1810 return Err(custom_error(ctx, "Count must be non-negative"));
1811 }
1812
1813 let result: Vec<Value> = (0..n).map(|_| value.clone()).collect();
1814 Ok(Value::Array(result))
1815 }
1816}
1817
1818defn!(CycleFn, vec![arg!(array), arg!(number)], None);
1823
1824impl Function for CycleFn {
1825 fn evaluate(&self, args: &[Value], ctx: &mut Context<'_>) -> SearchResult {
1826 self.signature.validate(args, ctx)?;
1827
1828 let arr = args[0]
1829 .as_array()
1830 .ok_or_else(|| custom_error(ctx, "Expected array argument"))?;
1831
1832 let n = args[1]
1833 .as_f64()
1834 .ok_or_else(|| custom_error(ctx, "Expected number for count argument"))?
1835 as i64;
1836
1837 if n < 0 {
1838 return Err(custom_error(ctx, "Count must be non-negative"));
1839 }
1840
1841 if arr.is_empty() || n == 0 {
1842 return Ok(Value::Array(vec![]));
1843 }
1844
1845 let mut result: Vec<Value> = Vec::with_capacity(arr.len() * n as usize);
1846 for _ in 0..n {
1847 result.extend(arr.iter().cloned());
1848 }
1849 Ok(Value::Array(result))
1850 }
1851}
1852
1853#[cfg(test)]
1854mod tests {
1855 use crate::Runtime;
1856 use serde_json::json;
1857
1858 fn setup_runtime() -> Runtime {
1859 Runtime::builder()
1860 .with_standard()
1861 .with_all_extensions()
1862 .build()
1863 }
1864
1865 #[test]
1866 fn test_unique() {
1867 let runtime = setup_runtime();
1868 let expr = runtime.compile("unique(@)").unwrap();
1869 let data = json!([1, 2, 1]);
1870 let result = expr.search(&data).unwrap();
1871 let arr = result.as_array().unwrap();
1872 assert_eq!(arr.len(), 2);
1873 }
1874
1875 #[test]
1876 fn test_first() {
1877 let runtime = setup_runtime();
1878 let expr = runtime.compile("first(@)").unwrap();
1879 let data = json!([1, 2]);
1880 let result = expr.search(&data).unwrap();
1881 assert_eq!(result.as_f64().unwrap() as i64, 1);
1882 }
1883
1884 #[test]
1885 fn test_last() {
1886 let runtime = setup_runtime();
1887 let expr = runtime.compile("last(@)").unwrap();
1888 let data = json!([1, 2]);
1889 let result = expr.search(&data).unwrap();
1890 assert_eq!(result.as_f64().unwrap() as i64, 2);
1891 }
1892
1893 #[test]
1894 fn test_range() {
1895 let runtime = setup_runtime();
1896 let expr = runtime.compile("range(`0`, `5`)").unwrap();
1897 let data = json!(null);
1898 let result = expr.search(&data).unwrap();
1899 let arr = result.as_array().unwrap();
1900 assert_eq!(arr.len(), 5);
1901 }
1902
1903 #[test]
1904 fn test_butlast() {
1905 let runtime = setup_runtime();
1907 let expr = runtime.compile("butlast(@)").unwrap();
1908 let data = json!([1, 2, 3]);
1909 let result = expr.search(&data).unwrap();
1910 let arr = result.as_array().unwrap();
1911 assert_eq!(arr.len(), 2);
1912 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
1913 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
1914 }
1915
1916 #[test]
1917 fn test_interpose() {
1918 let runtime = setup_runtime();
1919 let expr = runtime.compile("interpose(@, `0`)").unwrap();
1920 let data = json!([1, 2, 3]);
1921 let result = expr.search(&data).unwrap();
1922 let arr = result.as_array().unwrap();
1923 assert_eq!(arr.len(), 5);
1924 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
1925 assert_eq!(arr[1].as_f64().unwrap() as i64, 0);
1926 assert_eq!(arr[2].as_f64().unwrap() as i64, 2);
1927 assert_eq!(arr[3].as_f64().unwrap() as i64, 0);
1928 assert_eq!(arr[4].as_f64().unwrap() as i64, 3);
1929 }
1930
1931 #[test]
1932 fn test_interpose_empty() {
1933 let runtime = setup_runtime();
1934 let expr = runtime.compile("interpose(@, `0`)").unwrap();
1935 let data = json!([]);
1936 let result = expr.search(&data).unwrap();
1937 let arr = result.as_array().unwrap();
1938 assert_eq!(arr.len(), 0);
1939 }
1940
1941 #[test]
1942 fn test_interpose_single() {
1943 let runtime = setup_runtime();
1944 let expr = runtime.compile("interpose(@, `0`)").unwrap();
1945 let data = json!([1]);
1946 let result = expr.search(&data).unwrap();
1947 let arr = result.as_array().unwrap();
1948 assert_eq!(arr.len(), 1);
1949 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
1950 }
1951
1952 #[test]
1953 fn test_interpose_string_separator() {
1954 let runtime = setup_runtime();
1955 let expr = runtime.compile("interpose(@, `\"-\"`)").unwrap();
1956 let data = json!(["a", "b", "c"]);
1957 let result = expr.search(&data).unwrap();
1958 let arr = result.as_array().unwrap();
1959 assert_eq!(arr.len(), 5);
1960 assert_eq!(arr[0].as_str().unwrap(), "a");
1961 assert_eq!(arr[1].as_str().unwrap(), "-");
1962 assert_eq!(arr[2].as_str().unwrap(), "b");
1963 assert_eq!(arr[3].as_str().unwrap(), "-");
1964 assert_eq!(arr[4].as_str().unwrap(), "c");
1965 }
1966
1967 #[test]
1968 fn test_zipmap() {
1969 let runtime = setup_runtime();
1970 let expr = runtime
1971 .compile("zipmap(`[\"a\", \"b\", \"c\"]`, `[1, 2, 3]`)")
1972 .unwrap();
1973 let data = json!(null);
1974 let result = expr.search(&data).unwrap();
1975 let obj = result.as_object().unwrap();
1976 assert_eq!(obj.len(), 3);
1977 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 1);
1978 assert_eq!(obj.get("b").unwrap().as_f64().unwrap() as i64, 2);
1979 assert_eq!(obj.get("c").unwrap().as_f64().unwrap() as i64, 3);
1980 }
1981
1982 #[test]
1983 fn test_zipmap_unequal_lengths() {
1984 let runtime = setup_runtime();
1985 let expr = runtime
1987 .compile("zipmap(`[\"x\", \"y\"]`, `[10, 20, 30]`)")
1988 .unwrap();
1989 let data = json!(null);
1990 let result = expr.search(&data).unwrap();
1991 let obj = result.as_object().unwrap();
1992 assert_eq!(obj.len(), 2);
1993 assert_eq!(obj.get("x").unwrap().as_f64().unwrap() as i64, 10);
1994 assert_eq!(obj.get("y").unwrap().as_f64().unwrap() as i64, 20);
1995 }
1996
1997 #[test]
1998 fn test_zipmap_empty() {
1999 let runtime = setup_runtime();
2000 let expr = runtime.compile("zipmap(`[]`, `[]`)").unwrap();
2001 let data = json!(null);
2002 let result = expr.search(&data).unwrap();
2003 let obj = result.as_object().unwrap();
2004 assert_eq!(obj.len(), 0);
2005 }
2006
2007 #[test]
2008 fn test_partition_by() {
2009 let runtime = setup_runtime();
2010 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2012 let data: serde_json::Value = serde_json::from_str(
2013 r#"[{"type": "a", "v": 1}, {"type": "a", "v": 2}, {"type": "b", "v": 3}, {"type": "a", "v": 4}]"#,
2014 )
2015 .unwrap();
2016 let result = expr.search(&data).unwrap();
2017 let arr = result.as_array().unwrap();
2018 assert_eq!(arr.len(), 3);
2019
2020 let partition1 = arr[0].as_array().unwrap();
2021 assert_eq!(partition1.len(), 2); let partition2 = arr[1].as_array().unwrap();
2024 assert_eq!(partition2.len(), 1); let partition3 = arr[2].as_array().unwrap();
2027 assert_eq!(partition3.len(), 1); }
2029
2030 #[test]
2031 fn test_partition_by_primitives() {
2032 let runtime = setup_runtime();
2033 let expr = runtime.compile(r#"partition_by(@, `"_"`)"#).unwrap();
2035 let data = json!([1, 1, 2, 2, 1, 1]);
2036 let result = expr.search(&data).unwrap();
2037 let arr = result.as_array().unwrap();
2038 assert_eq!(arr.len(), 3);
2039
2040 let partition1 = arr[0].as_array().unwrap();
2041 assert_eq!(partition1.len(), 2);
2042 assert_eq!(partition1[0].as_f64().unwrap() as i64, 1);
2043
2044 let partition2 = arr[1].as_array().unwrap();
2045 assert_eq!(partition2.len(), 2);
2046 assert_eq!(partition2[0].as_f64().unwrap() as i64, 2);
2047
2048 let partition3 = arr[2].as_array().unwrap();
2049 assert_eq!(partition3.len(), 2);
2050 assert_eq!(partition3[0].as_f64().unwrap() as i64, 1);
2051 }
2052
2053 #[test]
2054 fn test_partition_by_empty() {
2055 let runtime = setup_runtime();
2056 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2057 let data = json!([]);
2058 let result = expr.search(&data).unwrap();
2059 let arr = result.as_array().unwrap();
2060 assert_eq!(arr.len(), 0);
2061 }
2062
2063 #[test]
2064 fn test_partition_by_single() {
2065 let runtime = setup_runtime();
2066 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2067 let data: serde_json::Value = serde_json::from_str(r#"[{"type": "a"}]"#).unwrap();
2068 let result = expr.search(&data).unwrap();
2069 let arr = result.as_array().unwrap();
2070 assert_eq!(arr.len(), 1);
2071 let partition1 = arr[0].as_array().unwrap();
2072 assert_eq!(partition1.len(), 1);
2073 }
2074
2075 #[test]
2076 fn test_dedupe() {
2077 let runtime = setup_runtime();
2078 let expr = runtime.compile("dedupe(@)").unwrap();
2079 let data = json!([1, 1, 2, 2, 1, 1]);
2080 let result = expr.search(&data).unwrap();
2081 let arr = result.as_array().unwrap();
2082 assert_eq!(arr.len(), 3);
2083 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2084 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
2085 assert_eq!(arr[2].as_f64().unwrap() as i64, 1);
2086 }
2087
2088 #[test]
2089 fn test_dedupe_empty() {
2090 let runtime = setup_runtime();
2091 let expr = runtime.compile("dedupe(@)").unwrap();
2092 let data = json!([]);
2093 let result = expr.search(&data).unwrap();
2094 let arr = result.as_array().unwrap();
2095 assert_eq!(arr.len(), 0);
2096 }
2097
2098 #[test]
2099 fn test_dedupe_no_consecutive() {
2100 let runtime = setup_runtime();
2101 let expr = runtime.compile("dedupe(@)").unwrap();
2102 let data = json!([1, 2, 3]);
2103 let result = expr.search(&data).unwrap();
2104 let arr = result.as_array().unwrap();
2105 assert_eq!(arr.len(), 3);
2106 }
2107
2108 #[test]
2109 fn test_dedupe_strings() {
2110 let runtime = setup_runtime();
2111 let expr = runtime.compile("dedupe(@)").unwrap();
2112 let data = json!(["a", "a", "b", "a"]);
2113 let result = expr.search(&data).unwrap();
2114 let arr = result.as_array().unwrap();
2115 assert_eq!(arr.len(), 3);
2116 assert_eq!(arr[0].as_str().unwrap(), "a");
2117 assert_eq!(arr[1].as_str().unwrap(), "b");
2118 assert_eq!(arr[2].as_str().unwrap(), "a");
2119 }
2120
2121 #[test]
2122 fn test_dedupe_objects() {
2123 let runtime = setup_runtime();
2124 let expr = runtime.compile("dedupe(@)").unwrap();
2125 let data: serde_json::Value =
2126 serde_json::from_str(r#"[{"x": 1}, {"x": 1}, {"x": 2}, {"x": 1}]"#).unwrap();
2127 let result = expr.search(&data).unwrap();
2128 let arr = result.as_array().unwrap();
2129 assert_eq!(arr.len(), 3);
2130 }
2131
2132 #[test]
2133 fn test_dedupe_all_same() {
2134 let runtime = setup_runtime();
2135 let expr = runtime.compile("dedupe(@)").unwrap();
2136 let data = json!([1, 1, 1]);
2137 let result = expr.search(&data).unwrap();
2138 let arr = result.as_array().unwrap();
2139 assert_eq!(arr.len(), 1);
2140 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2141 }
2142
2143 #[test]
2144 fn test_zipmap_duplicate_keys() {
2145 let runtime = setup_runtime();
2147 let expr = runtime
2148 .compile("zipmap(`[\"a\", \"b\", \"a\"]`, `[1, 2, 3]`)")
2149 .unwrap();
2150 let data = json!(null);
2151 let result = expr.search(&data).unwrap();
2152 let obj = result.as_object().unwrap();
2153 assert_eq!(obj.len(), 2);
2154 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 3); assert_eq!(obj.get("b").unwrap().as_f64().unwrap() as i64, 2);
2156 }
2157
2158 #[test]
2159 fn test_zipmap_values_longer() {
2160 let runtime = setup_runtime();
2161 let expr = runtime.compile("zipmap(`[\"a\"]`, `[1, 2, 3]`)").unwrap();
2162 let data = json!(null);
2163 let result = expr.search(&data).unwrap();
2164 let obj = result.as_object().unwrap();
2165 assert_eq!(obj.len(), 1);
2166 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 1);
2167 }
2168
2169 #[test]
2170 fn test_partition_by_missing_field() {
2171 let runtime = setup_runtime();
2172 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2173 let data: serde_json::Value =
2175 serde_json::from_str(r#"[{"type": "a"}, {"name": "no-type"}, {"type": "a"}]"#).unwrap();
2176 let result = expr.search(&data).unwrap();
2177 let arr = result.as_array().unwrap();
2178 assert_eq!(arr.len(), 3);
2180 }
2181
2182 #[test]
2183 fn test_partition_by_all_same() {
2184 let runtime = setup_runtime();
2185 let expr = runtime.compile(r#"partition_by(@, `"type"`)"#).unwrap();
2186 let data: serde_json::Value =
2187 serde_json::from_str(r#"[{"type": "a"}, {"type": "a"}, {"type": "a"}]"#).unwrap();
2188 let result = expr.search(&data).unwrap();
2189 let arr = result.as_array().unwrap();
2190 assert_eq!(arr.len(), 1);
2191 let partition = arr[0].as_array().unwrap();
2192 assert_eq!(partition.len(), 3);
2193 }
2194
2195 #[test]
2196 fn test_interpose_null_separator() {
2197 let runtime = setup_runtime();
2198 let expr = runtime.compile("interpose(@, `null`)").unwrap();
2199 let data = json!([1, 2]);
2200 let result = expr.search(&data).unwrap();
2201 let arr = result.as_array().unwrap();
2202 assert_eq!(arr.len(), 3);
2203 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2204 assert!(arr[1].is_null());
2205 assert_eq!(arr[2].as_f64().unwrap() as i64, 2);
2206 }
2207
2208 #[test]
2209 fn test_interpose_object_separator() {
2210 let runtime = setup_runtime();
2211 let expr = runtime.compile(r#"interpose(@, `{"sep": true}`)"#).unwrap();
2212 let data = json!([1, 2]);
2213 let result = expr.search(&data).unwrap();
2214 let arr = result.as_array().unwrap();
2215 assert_eq!(arr.len(), 3);
2216 assert!(arr[1].as_object().is_some());
2217 }
2218
2219 #[test]
2224 fn test_zip_basic() {
2225 let runtime = setup_runtime();
2226 let data: serde_json::Value =
2227 serde_json::from_str(r#"{"a": [1, 2, 3], "b": ["x", "y", "z"]}"#).unwrap();
2228 let expr = runtime.compile("zip(a, b)").unwrap();
2229 let result = expr.search(&data).unwrap();
2230 let arr = result.as_array().unwrap();
2231 assert_eq!(arr.len(), 3);
2232 assert_eq!(arr[0].as_array().unwrap()[0].as_f64().unwrap() as i64, 1);
2233 assert_eq!(arr[0].as_array().unwrap()[1].as_str().unwrap(), "x");
2234 }
2235
2236 #[test]
2237 fn test_zip_unequal_lengths() {
2238 let runtime = setup_runtime();
2239 let data: serde_json::Value =
2240 serde_json::from_str(r#"{"a": [1, 2], "b": ["x", "y", "z"]}"#).unwrap();
2241 let expr = runtime.compile("zip(a, b)").unwrap();
2242 let result = expr.search(&data).unwrap();
2243 let arr = result.as_array().unwrap();
2244 assert_eq!(arr.len(), 2);
2246 }
2247
2248 #[test]
2249 fn test_zip_empty_array() {
2250 let runtime = setup_runtime();
2251 let data: serde_json::Value = serde_json::from_str(r#"{"a": [], "b": [1, 2, 3]}"#).unwrap();
2252 let expr = runtime.compile("zip(a, b)").unwrap();
2253 let result = expr.search(&data).unwrap();
2254 let arr = result.as_array().unwrap();
2255 assert_eq!(arr.len(), 0);
2256 }
2257
2258 #[test]
2259 fn test_zip_with_objects() {
2260 let runtime = setup_runtime();
2261 let data: serde_json::Value =
2262 serde_json::from_str(r#"{"names": ["Alice", "Bob"], "scores": [95, 87]}"#).unwrap();
2263 let expr = runtime.compile("zip(names, scores)").unwrap();
2264 let result = expr.search(&data).unwrap();
2265 let arr = result.as_array().unwrap();
2266 assert_eq!(arr.len(), 2);
2267 assert_eq!(arr[0].as_array().unwrap()[0].as_str().unwrap(), "Alice");
2268 assert_eq!(arr[0].as_array().unwrap()[1].as_f64().unwrap() as i64, 95);
2269 }
2270
2271 #[test]
2276 fn test_chunk_basic() {
2277 let runtime = setup_runtime();
2278 let data = json!([1, 2, 3, 4, 5]);
2279 let expr = runtime.compile("chunk(@, `2`)").unwrap();
2280 let result = expr.search(&data).unwrap();
2281 let arr = result.as_array().unwrap();
2282 assert_eq!(arr.len(), 3); assert_eq!(arr[0].as_array().unwrap().len(), 2);
2284 assert_eq!(arr[2].as_array().unwrap().len(), 1);
2285 }
2286
2287 #[test]
2288 fn test_chunk_exact_fit() {
2289 let runtime = setup_runtime();
2290 let data = json!([1, 2, 3, 4, 5, 6]);
2291 let expr = runtime.compile("chunk(@, `3`)").unwrap();
2292 let result = expr.search(&data).unwrap();
2293 let arr = result.as_array().unwrap();
2294 assert_eq!(arr.len(), 2);
2295 assert_eq!(arr[0].as_array().unwrap().len(), 3);
2296 assert_eq!(arr[1].as_array().unwrap().len(), 3);
2297 }
2298
2299 #[test]
2300 fn test_chunk_size_larger_than_array() {
2301 let runtime = setup_runtime();
2302 let data = json!([1, 2, 3]);
2303 let expr = runtime.compile("chunk(@, `10`)").unwrap();
2304 let result = expr.search(&data).unwrap();
2305 let arr = result.as_array().unwrap();
2306 assert_eq!(arr.len(), 1);
2307 assert_eq!(arr[0].as_array().unwrap().len(), 3);
2308 }
2309
2310 #[test]
2311 fn test_chunk_size_one() {
2312 let runtime = setup_runtime();
2313 let data = json!([1, 2, 3]);
2314 let expr = runtime.compile("chunk(@, `1`)").unwrap();
2315 let result = expr.search(&data).unwrap();
2316 let arr = result.as_array().unwrap();
2317 assert_eq!(arr.len(), 3);
2318 }
2319
2320 #[test]
2321 fn test_chunk_and_process_pipeline() {
2322 let runtime = setup_runtime();
2323 let data = json!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2324 let expr = runtime.compile("chunk(@, `3`)").unwrap();
2325 let result = expr.search(&data).unwrap();
2326 let arr = result.as_array().unwrap();
2327 assert_eq!(arr.len(), 4);
2329 }
2330
2331 #[test]
2336 fn test_take_basic() {
2337 let runtime = setup_runtime();
2338 let data = json!([1, 2, 3, 4, 5]);
2339 let expr = runtime.compile("take(@, `3`)").unwrap();
2340 let result = expr.search(&data).unwrap();
2341 let arr = result.as_array().unwrap();
2342 assert_eq!(arr.len(), 3);
2343 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2344 assert_eq!(arr[2].as_f64().unwrap() as i64, 3);
2345 }
2346
2347 #[test]
2348 fn test_take_more_than_length() {
2349 let runtime = setup_runtime();
2350 let data = json!([1, 2]);
2351 let expr = runtime.compile("take(@, `10`)").unwrap();
2352 let result = expr.search(&data).unwrap();
2353 let arr = result.as_array().unwrap();
2354 assert_eq!(arr.len(), 2);
2355 }
2356
2357 #[test]
2358 fn test_take_zero() {
2359 let runtime = setup_runtime();
2360 let data = json!([1, 2, 3]);
2361 let expr = runtime.compile("take(@, `0`)").unwrap();
2362 let result = expr.search(&data).unwrap();
2363 let arr = result.as_array().unwrap();
2364 assert_eq!(arr.len(), 0);
2365 }
2366
2367 #[test]
2372 fn test_drop_basic() {
2373 let runtime = setup_runtime();
2374 let data = json!([1, 2, 3, 4, 5]);
2375 let expr = runtime.compile("drop(@, `2`)").unwrap();
2376 let result = expr.search(&data).unwrap();
2377 let arr = result.as_array().unwrap();
2378 assert_eq!(arr.len(), 3);
2379 assert_eq!(arr[0].as_f64().unwrap() as i64, 3);
2380 }
2381
2382 #[test]
2383 fn test_drop_more_than_length() {
2384 let runtime = setup_runtime();
2385 let data = json!([1, 2]);
2386 let expr = runtime.compile("drop(@, `10`)").unwrap();
2387 let result = expr.search(&data).unwrap();
2388 let arr = result.as_array().unwrap();
2389 assert_eq!(arr.len(), 0);
2390 }
2391
2392 #[test]
2393 fn test_drop_zero() {
2394 let runtime = setup_runtime();
2395 let data = json!([1, 2, 3]);
2396 let expr = runtime.compile("drop(@, `0`)").unwrap();
2397 let result = expr.search(&data).unwrap();
2398 let arr = result.as_array().unwrap();
2399 assert_eq!(arr.len(), 3);
2400 }
2401
2402 #[test]
2407 fn test_flatten_deep_basic() {
2408 let runtime = setup_runtime();
2409 let data = json!([[1, 2], [3, 4]]);
2410 let expr = runtime.compile("flatten_deep(@)").unwrap();
2411 let result = expr.search(&data).unwrap();
2412 let arr = result.as_array().unwrap();
2413 assert_eq!(arr.len(), 4);
2414 }
2415
2416 #[test]
2417 fn test_flatten_deep_nested() {
2418 let runtime = setup_runtime();
2419 let data = json!([1, [2, [3, [4, [5]]]]]);
2420 let expr = runtime.compile("flatten_deep(@)").unwrap();
2421 let result = expr.search(&data).unwrap();
2422 let arr = result.as_array().unwrap();
2423 assert_eq!(arr.len(), 5);
2424 assert_eq!(arr[4].as_f64().unwrap() as i64, 5);
2425 }
2426
2427 #[test]
2428 fn test_flatten_deep_already_flat() {
2429 let runtime = setup_runtime();
2430 let data = json!([1, 2, 3]);
2431 let expr = runtime.compile("flatten_deep(@)").unwrap();
2432 let result = expr.search(&data).unwrap();
2433 let arr = result.as_array().unwrap();
2434 assert_eq!(arr.len(), 3);
2435 }
2436
2437 #[test]
2438 fn test_flatten_deep_mixed() {
2439 let runtime = setup_runtime();
2440 let data = json!([1, [2, 3], [[4]], [[[5, 6]]]]);
2441 let expr = runtime.compile("flatten_deep(@)").unwrap();
2442 let result = expr.search(&data).unwrap();
2443 let arr = result.as_array().unwrap();
2444 assert_eq!(arr.len(), 6);
2445 }
2446
2447 #[test]
2452 fn test_compact_basic() {
2453 let runtime = setup_runtime();
2454 let data = json!([1, null, 2, false, 3]);
2455 let expr = runtime.compile("compact(@)").unwrap();
2456 let result = expr.search(&data).unwrap();
2457 let arr = result.as_array().unwrap();
2458 assert_eq!(arr.len(), 3);
2459 }
2460
2461 #[test]
2462 fn test_compact_keeps_zero_and_empty_string() {
2463 let runtime = setup_runtime();
2464 let data = json!([0, "", null, true]);
2465 let expr = runtime.compile("compact(@)").unwrap();
2466 let result = expr.search(&data).unwrap();
2467 let arr = result.as_array().unwrap();
2468 assert_eq!(arr.len(), 3); }
2470
2471 #[test]
2472 fn test_compact_all_falsy() {
2473 let runtime = setup_runtime();
2474 let data = json!([null, false, null]);
2475 let expr = runtime.compile("compact(@)").unwrap();
2476 let result = expr.search(&data).unwrap();
2477 let arr = result.as_array().unwrap();
2478 assert_eq!(arr.len(), 0);
2479 }
2480
2481 #[test]
2486 fn test_index_at_positive() {
2487 let runtime = setup_runtime();
2488 let data = json!(["a", "b", "c", "d"]);
2489 let expr = runtime.compile("index_at(@, `2`)").unwrap();
2490 let result = expr.search(&data).unwrap();
2491 assert_eq!(result.as_str().unwrap(), "c");
2492 }
2493
2494 #[test]
2495 fn test_index_at_negative() {
2496 let runtime = setup_runtime();
2497 let data = json!(["a", "b", "c", "d"]);
2498 let expr = runtime.compile("index_at(@, `-1`)").unwrap();
2499 let result = expr.search(&data).unwrap();
2500 assert_eq!(result.as_str().unwrap(), "d");
2501 }
2502
2503 #[test]
2504 fn test_index_at_negative_second() {
2505 let runtime = setup_runtime();
2506 let data = json!(["a", "b", "c", "d"]);
2507 let expr = runtime.compile("index_at(@, `-2`)").unwrap();
2508 let result = expr.search(&data).unwrap();
2509 assert_eq!(result.as_str().unwrap(), "c");
2510 }
2511
2512 #[test]
2513 fn test_index_at_out_of_bounds() {
2514 let runtime = setup_runtime();
2515 let data = json!(["a", "b", "c"]);
2516 let expr = runtime.compile("index_at(@, `10`)").unwrap();
2517 let result = expr.search(&data).unwrap();
2518 assert!(result.is_null());
2519 }
2520
2521 #[test]
2526 fn test_includes_number() {
2527 let runtime = setup_runtime();
2528 let data = json!([1, 2, 3, 4, 5]);
2529 let expr = runtime.compile("includes(@, `3`)").unwrap();
2530 let result = expr.search(&data).unwrap();
2531 assert!(result.as_bool().unwrap());
2532 }
2533
2534 #[test]
2535 fn test_includes_not_found() {
2536 let runtime = setup_runtime();
2537 let data = json!([1, 2, 3]);
2538 let expr = runtime.compile("includes(@, `10`)").unwrap();
2539 let result = expr.search(&data).unwrap();
2540 assert!(!result.as_bool().unwrap());
2541 }
2542
2543 #[test]
2544 fn test_includes_string() {
2545 let runtime = setup_runtime();
2546 let data = json!(["apple", "banana", "cherry"]);
2547 let expr = runtime.compile(r#"includes(@, `"banana"`)"#).unwrap();
2548 let result = expr.search(&data).unwrap();
2549 assert!(result.as_bool().unwrap());
2550 }
2551
2552 #[test]
2553 fn test_includes_object() {
2554 let runtime = setup_runtime();
2555 let data = json!([{"a": 1}, {"b": 2}]);
2556 let expr = runtime.compile(r#"includes(@, `{"a": 1}`)"#).unwrap();
2557 let result = expr.search(&data).unwrap();
2558 assert!(result.as_bool().unwrap());
2559 }
2560
2561 #[test]
2566 fn test_find_index_found() {
2567 let runtime = setup_runtime();
2568 let data = json!(["a", "b", "c", "d"]);
2569 let expr = runtime.compile(r#"find_index(@, `"c"`)"#).unwrap();
2570 let result = expr.search(&data).unwrap();
2571 assert_eq!(result.as_f64().unwrap() as i64, 2);
2572 }
2573
2574 #[test]
2575 fn test_find_index_not_found() {
2576 let runtime = setup_runtime();
2577 let data = json!(["a", "b", "c"]);
2578 let expr = runtime.compile(r#"find_index(@, `"z"`)"#).unwrap();
2579 let result = expr.search(&data).unwrap();
2580 assert_eq!(result.as_f64().unwrap() as i64, -1);
2581 }
2582
2583 #[test]
2588 fn test_group_by_basic() {
2589 let runtime = setup_runtime();
2590 let data: serde_json::Value = serde_json::from_str(
2591 r#"[{"type": "a", "v": 1}, {"type": "b", "v": 2}, {"type": "a", "v": 3}]"#,
2592 )
2593 .unwrap();
2594 let expr = runtime.compile(r#"group_by(@, `"type"`)"#).unwrap();
2595 let result = expr.search(&data).unwrap();
2596 let obj = result.as_object().unwrap();
2597 assert_eq!(obj.get("a").unwrap().as_array().unwrap().len(), 2);
2598 assert_eq!(obj.get("b").unwrap().as_array().unwrap().len(), 1);
2599 }
2600
2601 #[test]
2606 fn test_index_by_basic() {
2607 let runtime = setup_runtime();
2608 let data: serde_json::Value =
2609 serde_json::from_str(r#"[{"id": 1, "name": "alice"}, {"id": 2, "name": "bob"}]"#)
2610 .unwrap();
2611 let expr = runtime.compile(r#"index_by(@, `"id"`)"#).unwrap();
2612 let result = expr.search(&data).unwrap();
2613 let obj = result.as_object().unwrap();
2614 assert_eq!(obj.len(), 2);
2615 let alice = obj.get("1").unwrap().as_object().unwrap();
2617 assert_eq!(alice.get("name").unwrap().as_str().unwrap(), "alice");
2618 let bob = obj.get("2").unwrap().as_object().unwrap();
2619 assert_eq!(bob.get("name").unwrap().as_str().unwrap(), "bob");
2620 }
2621
2622 #[test]
2623 fn test_index_by_string_key() {
2624 let runtime = setup_runtime();
2625 let data: serde_json::Value = serde_json::from_str(
2626 r#"[{"code": "US", "name": "United States"}, {"code": "UK", "name": "United Kingdom"}]"#,
2627 )
2628 .unwrap();
2629 let expr = runtime.compile(r#"index_by(@, `"code"`)"#).unwrap();
2630 let result = expr.search(&data).unwrap();
2631 let obj = result.as_object().unwrap();
2632 assert_eq!(obj.len(), 2);
2633 let us = obj.get("US").unwrap().as_object().unwrap();
2634 assert_eq!(us.get("name").unwrap().as_str().unwrap(), "United States");
2635 }
2636
2637 #[test]
2638 fn test_index_by_duplicate_keys() {
2639 let runtime = setup_runtime();
2641 let data: serde_json::Value = serde_json::from_str(
2642 r#"[{"type": "a", "v": 1}, {"type": "a", "v": 2}, {"type": "a", "v": 3}]"#,
2643 )
2644 .unwrap();
2645 let expr = runtime.compile(r#"index_by(@, `"type"`)"#).unwrap();
2646 let result = expr.search(&data).unwrap();
2647 let obj = result.as_object().unwrap();
2648 assert_eq!(obj.len(), 1);
2649 let a = obj.get("a").unwrap().as_object().unwrap();
2651 assert_eq!(a.get("v").unwrap().as_f64().unwrap() as i64, 3);
2652 }
2653
2654 #[test]
2655 fn test_index_by_missing_key() {
2656 let runtime = setup_runtime();
2658 let data: serde_json::Value = serde_json::from_str(
2659 r#"[{"id": 1, "name": "alice"}, {"name": "bob"}, {"id": 3, "name": "charlie"}]"#,
2660 )
2661 .unwrap();
2662 let expr = runtime.compile(r#"index_by(@, `"id"`)"#).unwrap();
2663 let result = expr.search(&data).unwrap();
2664 let obj = result.as_object().unwrap();
2665 assert_eq!(obj.len(), 2);
2666 assert!(obj.contains_key("1"));
2667 assert!(obj.contains_key("3"));
2668 assert!(!obj.contains_key("2")); }
2670
2671 #[test]
2672 fn test_index_by_empty_array() {
2673 let runtime = setup_runtime();
2674 let data = json!([]);
2675 let expr = runtime.compile(r#"index_by(@, `"id"`)"#).unwrap();
2676 let result = expr.search(&data).unwrap();
2677 let obj = result.as_object().unwrap();
2678 assert!(obj.is_empty());
2679 }
2680
2681 #[test]
2686 fn test_difference() {
2687 let runtime = setup_runtime();
2688 let data: serde_json::Value =
2689 serde_json::from_str(r#"{"a": [1, 2, 3, 4], "b": [2, 4]}"#).unwrap();
2690 let expr = runtime.compile("difference(a, b)").unwrap();
2691 let result = expr.search(&data).unwrap();
2692 let arr = result.as_array().unwrap();
2693 assert_eq!(arr.len(), 2); }
2695
2696 #[test]
2697 fn test_intersection() {
2698 let runtime = setup_runtime();
2699 let data: serde_json::Value =
2700 serde_json::from_str(r#"{"a": [1, 2, 3], "b": [2, 3, 4]}"#).unwrap();
2701 let expr = runtime.compile("intersection(a, b)").unwrap();
2702 let result = expr.search(&data).unwrap();
2703 let arr = result.as_array().unwrap();
2704 assert_eq!(arr.len(), 2); }
2706
2707 #[test]
2708 fn test_union() {
2709 let runtime = setup_runtime();
2710 let data: serde_json::Value =
2711 serde_json::from_str(r#"{"a": [1, 2], "b": [2, 3]}"#).unwrap();
2712 let expr = runtime.compile("union(a, b)").unwrap();
2713 let result = expr.search(&data).unwrap();
2714 let arr = result.as_array().unwrap();
2715 assert_eq!(arr.len(), 3); }
2717
2718 #[test]
2723 fn test_frequencies_basic() {
2724 let runtime = setup_runtime();
2725 let data = json!(["a", "b", "a", "c", "a", "b"]);
2726 let expr = runtime.compile("frequencies(@)").unwrap();
2727 let result = expr.search(&data).unwrap();
2728 let obj = result.as_object().unwrap();
2729 assert_eq!(obj.get("a").unwrap().as_f64().unwrap() as i64, 3);
2730 assert_eq!(obj.get("b").unwrap().as_f64().unwrap() as i64, 2);
2731 assert_eq!(obj.get("c").unwrap().as_f64().unwrap() as i64, 1);
2732 }
2733
2734 #[test]
2735 fn test_frequencies_numbers() {
2736 let runtime = setup_runtime();
2737 let data = json!([1, 2, 1, 1, 2, 3]);
2738 let expr = runtime.compile("frequencies(@)").unwrap();
2739 let result = expr.search(&data).unwrap();
2740 let obj = result.as_object().unwrap();
2741 assert_eq!(obj.get("1").unwrap().as_f64().unwrap() as i64, 3);
2742 assert_eq!(obj.get("2").unwrap().as_f64().unwrap() as i64, 2);
2743 }
2744
2745 #[test]
2750 fn test_mode_basic() {
2751 let runtime = setup_runtime();
2752 let data = json!([1, 2, 2, 3, 2, 4]);
2753 let expr = runtime.compile("mode(@)").unwrap();
2754 let result = expr.search(&data).unwrap();
2755 assert_eq!(result.as_f64().unwrap() as i64, 2);
2756 }
2757
2758 #[test]
2759 fn test_mode_empty() {
2760 let runtime = setup_runtime();
2761 let data = json!([]);
2762 let expr = runtime.compile("mode(@)").unwrap();
2763 let result = expr.search(&data).unwrap();
2764 assert!(result.is_null());
2765 }
2766
2767 #[test]
2772 fn test_cartesian_basic() {
2773 let runtime = setup_runtime();
2774 let data: serde_json::Value =
2775 serde_json::from_str(r#"{"a": [1, 2], "b": ["x", "y"]}"#).unwrap();
2776 let expr = runtime.compile("cartesian(a, b)").unwrap();
2777 let result = expr.search(&data).unwrap();
2778 let arr = result.as_array().unwrap();
2779 assert_eq!(arr.len(), 4); }
2781
2782 #[test]
2783 fn test_cartesian_empty() {
2784 let runtime = setup_runtime();
2785 let data: serde_json::Value = serde_json::from_str(r#"{"a": [], "b": [1, 2]}"#).unwrap();
2786 let expr = runtime.compile("cartesian(a, b)").unwrap();
2787 let result = expr.search(&data).unwrap();
2788 let arr = result.as_array().unwrap();
2789 assert_eq!(arr.len(), 0);
2790 }
2791
2792 #[test]
2793 fn test_cartesian_n_way_two_arrays() {
2794 let runtime = setup_runtime();
2795 let data = json!([[1, 2], ["a", "b"]]);
2796 let expr = runtime.compile("cartesian(@)").unwrap();
2797 let result = expr.search(&data).unwrap();
2798 let arr = result.as_array().unwrap();
2799 assert_eq!(arr.len(), 4); }
2801
2802 #[test]
2803 fn test_cartesian_n_way_three_arrays() {
2804 let runtime = setup_runtime();
2805 let data = json!([[1, 2], ["a", "b"], [true, false]]);
2806 let expr = runtime.compile("cartesian(@)").unwrap();
2807 let result = expr.search(&data).unwrap();
2808 let arr = result.as_array().unwrap();
2809 assert_eq!(arr.len(), 8); }
2811
2812 #[test]
2813 fn test_cartesian_n_way_single_array() {
2814 let runtime = setup_runtime();
2815 let data = json!([[1, 2, 3]]);
2816 let expr = runtime.compile("cartesian(@)").unwrap();
2817 let result = expr.search(&data).unwrap();
2818 let arr = result.as_array().unwrap();
2819 assert_eq!(arr.len(), 3); }
2821
2822 #[test]
2823 fn test_cartesian_n_way_empty() {
2824 let runtime = setup_runtime();
2825 let data = json!([]);
2826 let expr = runtime.compile("cartesian(@)").unwrap();
2827 let result = expr.search(&data).unwrap();
2828 let arr = result.as_array().unwrap();
2829 assert_eq!(arr.len(), 0);
2830 }
2831
2832 #[test]
2837 fn test_first_empty_array() {
2838 let runtime = setup_runtime();
2839 let data = json!([]);
2840 let expr = runtime.compile("first(@)").unwrap();
2841 let result = expr.search(&data).unwrap();
2842 assert!(result.is_null());
2843 }
2844
2845 #[test]
2846 fn test_last_empty_array() {
2847 let runtime = setup_runtime();
2848 let data = json!([]);
2849 let expr = runtime.compile("last(@)").unwrap();
2850 let result = expr.search(&data).unwrap();
2851 assert!(result.is_null());
2852 }
2853
2854 #[test]
2855 fn test_unique_preserves_order() {
2856 let runtime = setup_runtime();
2857 let data = json!(["c", "a", "b", "a", "c"]);
2858 let expr = runtime.compile("unique(@)").unwrap();
2859 let result = expr.search(&data).unwrap();
2860 let arr = result.as_array().unwrap();
2861 assert_eq!(arr.len(), 3);
2862 assert_eq!(arr[0].as_str().unwrap(), "c");
2863 assert_eq!(arr[1].as_str().unwrap(), "a");
2864 assert_eq!(arr[2].as_str().unwrap(), "b");
2865 }
2866
2867 #[test]
2868 fn test_unique_different_types() {
2869 let runtime = setup_runtime();
2870 let data = json!([1, "1", 1, "1"]);
2871 let expr = runtime.compile("unique(@)").unwrap();
2872 let result = expr.search(&data).unwrap();
2873 let arr = result.as_array().unwrap();
2874 assert_eq!(arr.len(), 2); }
2876
2877 #[test]
2878 fn test_range_with_step() {
2879 let runtime = setup_runtime();
2880 let data = json!(null);
2881 let expr = runtime.compile("range(`1`, `10`, `2`)").unwrap();
2882 let result = expr.search(&data).unwrap();
2883 let arr = result.as_array().unwrap();
2884 assert_eq!(arr.len(), 5); assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
2886 assert_eq!(arr[4].as_f64().unwrap() as i64, 9);
2887 }
2888
2889 #[test]
2890 fn test_range_descending() {
2891 let runtime = setup_runtime();
2892 let data = json!(null);
2893 let expr = runtime.compile("range(`5`, `0`, `-1`)").unwrap();
2894 let result = expr.search(&data).unwrap();
2895 let arr = result.as_array().unwrap();
2896 assert_eq!(arr.len(), 5); assert_eq!(arr[0].as_f64().unwrap() as i64, 5);
2898 assert_eq!(arr[4].as_f64().unwrap() as i64, 1);
2899 }
2900
2901 #[test]
2906 fn test_pipeline_unique_sort() {
2907 let runtime = setup_runtime();
2908 let data = json!(["redis", "database", "redis", "nosql", "database"]);
2909 let expr = runtime.compile("unique(@) | sort(@)").unwrap();
2910 let result = expr.search(&data).unwrap();
2911 let arr = result.as_array().unwrap();
2912 assert_eq!(arr.len(), 3);
2913 assert_eq!(arr[0].as_str().unwrap(), "database");
2914 assert_eq!(arr[1].as_str().unwrap(), "nosql");
2915 assert_eq!(arr[2].as_str().unwrap(), "redis");
2916 }
2917
2918 #[test]
2919 fn test_pipeline_filter_take() {
2920 let runtime = setup_runtime();
2921 let data = json!([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
2922 let expr = runtime.compile("[?@ > `3`] | take(@, `3`)").unwrap();
2923 let result = expr.search(&data).unwrap();
2924 let arr = result.as_array().unwrap();
2925 assert_eq!(arr.len(), 3);
2926 assert_eq!(arr[0].as_f64().unwrap() as i64, 4);
2927 assert_eq!(arr[1].as_f64().unwrap() as i64, 5);
2928 assert_eq!(arr[2].as_f64().unwrap() as i64, 6);
2929 }
2930
2931 #[test]
2932 fn test_pipeline_flatten_unique() {
2933 let runtime = setup_runtime();
2934 let data = json!([[1, 2], [2, 3], [3, 4]]);
2935 let expr = runtime.compile("flatten_deep(@) | unique(@)").unwrap();
2936 let result = expr.search(&data).unwrap();
2937 let arr = result.as_array().unwrap();
2938 assert_eq!(arr.len(), 4); }
2940
2941 #[test]
2942 fn test_large_array_processing() {
2943 let runtime = setup_runtime();
2944 let items: Vec<i32> = (1..=1000).collect();
2946 let json_str = serde_json::to_string(&items).unwrap();
2947 let data: serde_json::Value = serde_json::from_str(&json_str).unwrap();
2948
2949 let expr = runtime.compile("length(@)").unwrap();
2950 let result = expr.search(&data).unwrap();
2951 assert_eq!(result.as_f64().unwrap() as i64, 1000);
2952 }
2953
2954 #[test]
2955 fn test_transpose_basic() {
2956 let runtime = setup_runtime();
2957 let data = json!([[1, 2, 3], [4, 5, 6]]);
2958 let expr = runtime.compile("transpose(@)").unwrap();
2959 let result = expr.search(&data).unwrap();
2960 let arr = result.as_array().unwrap();
2961 assert_eq!(arr.len(), 3);
2962 let col0 = arr[0].as_array().unwrap();
2964 assert_eq!(col0[0].as_f64().unwrap() as i64, 1);
2965 assert_eq!(col0[1].as_f64().unwrap() as i64, 4);
2966 let col1 = arr[1].as_array().unwrap();
2968 assert_eq!(col1[0].as_f64().unwrap() as i64, 2);
2969 assert_eq!(col1[1].as_f64().unwrap() as i64, 5);
2970 }
2971
2972 #[test]
2973 fn test_transpose_empty() {
2974 let runtime = setup_runtime();
2975 let data = json!([]);
2976 let expr = runtime.compile("transpose(@)").unwrap();
2977 let result = expr.search(&data).unwrap();
2978 let arr = result.as_array().unwrap();
2979 assert_eq!(arr.len(), 0);
2980 }
2981
2982 #[test]
2983 fn test_transpose_unequal_rows() {
2984 let runtime = setup_runtime();
2985 let data = json!([[1, 2], [3, 4, 5], [6, 7]]);
2986 let expr = runtime.compile("transpose(@)").unwrap();
2987 let result = expr.search(&data).unwrap();
2988 let arr = result.as_array().unwrap();
2989 assert_eq!(arr.len(), 2);
2991 }
2992
2993 #[test]
2994 fn test_pairwise_basic() {
2995 let runtime = setup_runtime();
2996 let data = json!([1, 2, 3, 4]);
2997 let expr = runtime.compile("pairwise(@)").unwrap();
2998 let result = expr.search(&data).unwrap();
2999 let arr = result.as_array().unwrap();
3000 assert_eq!(arr.len(), 3);
3001 let pair0 = arr[0].as_array().unwrap();
3003 assert_eq!(pair0[0].as_f64().unwrap() as i64, 1);
3004 assert_eq!(pair0[1].as_f64().unwrap() as i64, 2);
3005 let pair1 = arr[1].as_array().unwrap();
3007 assert_eq!(pair1[0].as_f64().unwrap() as i64, 2);
3008 assert_eq!(pair1[1].as_f64().unwrap() as i64, 3);
3009 }
3010
3011 #[test]
3012 fn test_pairwise_short_array() {
3013 let runtime = setup_runtime();
3014 let data = json!([1]);
3015 let expr = runtime.compile("pairwise(@)").unwrap();
3016 let result = expr.search(&data).unwrap();
3017 let arr = result.as_array().unwrap();
3018 assert_eq!(arr.len(), 0);
3019 }
3020
3021 #[test]
3022 fn test_sliding_window_alias() {
3023 let runtime = setup_runtime();
3024 let data = json!([1, 2, 3, 4, 5]);
3025 let expr = runtime.compile("sliding_window(@, `3`)").unwrap();
3026 let result = expr.search(&data).unwrap();
3027 let arr = result.as_array().unwrap();
3028 assert_eq!(arr.len(), 3);
3029 let win0 = arr[0].as_array().unwrap();
3031 assert_eq!(win0.len(), 3);
3032 assert_eq!(win0[0].as_f64().unwrap() as i64, 1);
3033 }
3034
3035 #[test]
3037 fn test_indices_array_found() {
3038 let runtime = setup_runtime();
3039 let data = json!([1, 2, 3, 2, 4, 2]);
3040 let expr = runtime.compile("indices_array(@, `2`)").unwrap();
3041 let result = expr.search(&data).unwrap();
3042 let arr = result.as_array().unwrap();
3043 assert_eq!(arr.len(), 3);
3044 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3045 assert_eq!(arr[1].as_f64().unwrap() as i64, 3);
3046 assert_eq!(arr[2].as_f64().unwrap() as i64, 5);
3047 }
3048
3049 #[test]
3050 fn test_indices_array_not_found() {
3051 let runtime = setup_runtime();
3052 let data = json!([1, 2, 3]);
3053 let expr = runtime.compile("indices_array(@, `5`)").unwrap();
3054 let result = expr.search(&data).unwrap();
3055 let arr = result.as_array().unwrap();
3056 assert_eq!(arr.len(), 0);
3057 }
3058
3059 #[test]
3060 fn test_indices_array_strings() {
3061 let runtime = setup_runtime();
3062 let data = json!(["a", "b", "a", "c", "a"]);
3063 let expr = runtime.compile(r#"indices_array(@, `"a"`)"#).unwrap();
3064 let result = expr.search(&data).unwrap();
3065 let arr = result.as_array().unwrap();
3066 assert_eq!(arr.len(), 3);
3067 assert_eq!(arr[0].as_f64().unwrap() as i64, 0);
3068 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
3069 assert_eq!(arr[2].as_f64().unwrap() as i64, 4);
3070 }
3071
3072 #[test]
3074 fn test_inside_array_true() {
3075 let runtime = setup_runtime();
3076 let data: serde_json::Value =
3077 serde_json::from_str(r#"{"a": [1, 2], "b": [1, 2, 3, 4]}"#).unwrap();
3078 let expr = runtime.compile("inside_array(a, b)").unwrap();
3079 let result = expr.search(&data).unwrap();
3080 assert!(result.as_bool().unwrap());
3081 }
3082
3083 #[test]
3084 fn test_inside_array_false() {
3085 let runtime = setup_runtime();
3086 let data: serde_json::Value =
3087 serde_json::from_str(r#"{"a": [1, 5], "b": [1, 2, 3, 4]}"#).unwrap();
3088 let expr = runtime.compile("inside_array(a, b)").unwrap();
3089 let result = expr.search(&data).unwrap();
3090 assert!(!result.as_bool().unwrap());
3091 }
3092
3093 #[test]
3094 fn test_inside_array_empty() {
3095 let runtime = setup_runtime();
3096 let data: serde_json::Value = serde_json::from_str(r#"{"a": [], "b": [1, 2, 3]}"#).unwrap();
3097 let expr = runtime.compile("inside_array(a, b)").unwrap();
3098 let result = expr.search(&data).unwrap();
3099 assert!(result.as_bool().unwrap());
3100 }
3101
3102 #[test]
3104 fn test_bsearch_found() {
3105 let runtime = setup_runtime();
3106 let data = json!([1, 3, 5, 7, 9]);
3107 let expr = runtime.compile("bsearch(@, `5`)").unwrap();
3108 let result = expr.search(&data).unwrap();
3109 assert_eq!(result.as_f64().unwrap() as i64, 2);
3110 }
3111
3112 #[test]
3113 fn test_bsearch_not_found_middle() {
3114 let runtime = setup_runtime();
3115 let data = json!([1, 3, 5, 7, 9]);
3116 let expr = runtime.compile("bsearch(@, `4`)").unwrap();
3117 let result = expr.search(&data).unwrap();
3118 assert_eq!(result.as_f64().unwrap() as i64, -3);
3119 }
3120
3121 #[test]
3122 fn test_bsearch_not_found_start() {
3123 let runtime = setup_runtime();
3124 let data = json!([1, 3, 5, 7, 9]);
3125 let expr = runtime.compile("bsearch(@, `0`)").unwrap();
3126 let result = expr.search(&data).unwrap();
3127 assert_eq!(result.as_f64().unwrap() as i64, -1);
3128 }
3129
3130 #[test]
3131 fn test_bsearch_not_found_end() {
3132 let runtime = setup_runtime();
3133 let data = json!([1, 3, 5, 7, 9]);
3134 let expr = runtime.compile("bsearch(@, `10`)").unwrap();
3135 let result = expr.search(&data).unwrap();
3136 assert_eq!(result.as_f64().unwrap() as i64, -6);
3137 }
3138
3139 #[test]
3140 fn test_bsearch_empty_array() {
3141 let runtime = setup_runtime();
3142 let data = json!([]);
3143 let expr = runtime.compile("bsearch(@, `5`)").unwrap();
3144 let result = expr.search(&data).unwrap();
3145 assert_eq!(result.as_f64().unwrap() as i64, -1);
3146 }
3147
3148 #[test]
3150 fn test_repeat_array_basic() {
3151 let runtime = setup_runtime();
3152 let data = json!(null);
3153 let expr = runtime.compile("repeat_array(`1`, `3`)").unwrap();
3154 let result = expr.search(&data).unwrap();
3155 let arr = result.as_array().unwrap();
3156 assert_eq!(arr.len(), 3);
3157 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3158 assert_eq!(arr[1].as_f64().unwrap() as i64, 1);
3159 assert_eq!(arr[2].as_f64().unwrap() as i64, 1);
3160 }
3161
3162 #[test]
3163 fn test_repeat_array_string() {
3164 let runtime = setup_runtime();
3165 let data = json!(null);
3166 let expr = runtime.compile(r#"repeat_array(`"x"`, `4`)"#).unwrap();
3167 let result = expr.search(&data).unwrap();
3168 let arr = result.as_array().unwrap();
3169 assert_eq!(arr.len(), 4);
3170 assert_eq!(arr[0].as_str().unwrap(), "x");
3171 assert_eq!(arr[3].as_str().unwrap(), "x");
3172 }
3173
3174 #[test]
3175 fn test_repeat_array_zero() {
3176 let runtime = setup_runtime();
3177 let data = json!(null);
3178 let expr = runtime.compile("repeat_array(`1`, `0`)").unwrap();
3179 let result = expr.search(&data).unwrap();
3180 let arr = result.as_array().unwrap();
3181 assert_eq!(arr.len(), 0);
3182 }
3183
3184 #[test]
3185 fn test_repeat_array_object() {
3186 let runtime = setup_runtime();
3187 let data = json!(null);
3188 let expr = runtime.compile(r#"repeat_array(`{"a": 1}`, `2`)"#).unwrap();
3189 let result = expr.search(&data).unwrap();
3190 let arr = result.as_array().unwrap();
3191 assert_eq!(arr.len(), 2);
3192 assert_eq!(
3193 arr[0]
3194 .as_object()
3195 .unwrap()
3196 .get("a")
3197 .unwrap()
3198 .as_f64()
3199 .unwrap() as i64,
3200 1
3201 );
3202 }
3203
3204 #[test]
3206 fn test_cycle_basic() {
3207 let runtime = setup_runtime();
3208 let data = json!([1, 2, 3]);
3209 let expr = runtime.compile("cycle(@, `2`)").unwrap();
3210 let result = expr.search(&data).unwrap();
3211 let arr = result.as_array().unwrap();
3212 assert_eq!(arr.len(), 6);
3213 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3214 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
3215 assert_eq!(arr[2].as_f64().unwrap() as i64, 3);
3216 assert_eq!(arr[3].as_f64().unwrap() as i64, 1);
3217 assert_eq!(arr[4].as_f64().unwrap() as i64, 2);
3218 assert_eq!(arr[5].as_f64().unwrap() as i64, 3);
3219 }
3220
3221 #[test]
3222 fn test_cycle_strings() {
3223 let runtime = setup_runtime();
3224 let data = json!(["a", "b"]);
3225 let expr = runtime.compile("cycle(@, `3`)").unwrap();
3226 let result = expr.search(&data).unwrap();
3227 let arr = result.as_array().unwrap();
3228 assert_eq!(arr.len(), 6);
3229 assert_eq!(arr[0].as_str().unwrap(), "a");
3230 assert_eq!(arr[1].as_str().unwrap(), "b");
3231 assert_eq!(arr[2].as_str().unwrap(), "a");
3232 }
3233
3234 #[test]
3235 fn test_cycle_zero() {
3236 let runtime = setup_runtime();
3237 let data = json!([1, 2, 3]);
3238 let expr = runtime.compile("cycle(@, `0`)").unwrap();
3239 let result = expr.search(&data).unwrap();
3240 let arr = result.as_array().unwrap();
3241 assert_eq!(arr.len(), 0);
3242 }
3243
3244 #[test]
3245 fn test_cycle_empty_array() {
3246 let runtime = setup_runtime();
3247 let data = json!([]);
3248 let expr = runtime.compile("cycle(@, `5`)").unwrap();
3249 let result = expr.search(&data).unwrap();
3250 let arr = result.as_array().unwrap();
3251 assert_eq!(arr.len(), 0);
3252 }
3253
3254 #[test]
3255 fn test_cycle_once() {
3256 let runtime = setup_runtime();
3257 let data = json!([1, 2]);
3258 let expr = runtime.compile("cycle(@, `1`)").unwrap();
3259 let result = expr.search(&data).unwrap();
3260 let arr = result.as_array().unwrap();
3261 assert_eq!(arr.len(), 2);
3262 assert_eq!(arr[0].as_f64().unwrap() as i64, 1);
3263 assert_eq!(arr[1].as_f64().unwrap() as i64, 2);
3264 }
3265}