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