Skip to main content

pick/selector/
extract.rs

1use crate::error::PickError;
2use serde_json::Value;
3use super::types::*;
4
5const MAX_EXTRACT_RESULTS: usize = 1_000_000;
6
7// ──────────────────────────────────────────────
8// Pipeline execution
9// ──────────────────────────────────────────────
10
11/// Execute a full expression (comma-separated pipelines) and return the
12/// union of all pipeline results.
13pub fn execute(value: &Value, expression: &Expression) -> Result<Vec<Value>, PickError> {
14    let single = expression.pipelines.len() == 1;
15    let mut all_results = Vec::new();
16
17    for pipeline in &expression.pipelines {
18        match execute_pipeline(value, pipeline) {
19            Ok(results) => all_results.extend(results),
20            Err(e) if !single => {
21                // In multi-selector mode, skip KeyNotFound for individual selectors
22                if !matches!(e, PickError::KeyNotFound(_)) {
23                    return Err(e);
24                }
25            }
26            Err(e) => return Err(e),
27        }
28    }
29
30    Ok(all_results)
31}
32
33/// Execute a single pipeline: feed value through each stage sequentially.
34pub fn execute_pipeline(value: &Value, pipeline: &Pipeline) -> Result<Vec<Value>, PickError> {
35    let mut current = vec![value.clone()];
36
37    for stage in &pipeline.stages {
38        current = execute_stage(&current, stage)?;
39    }
40
41    Ok(current)
42}
43
44fn execute_stage(inputs: &[Value], stage: &PipeStage) -> Result<Vec<Value>, PickError> {
45    match stage {
46        PipeStage::Path(selector) => {
47            let mut results = Vec::new();
48            for input in inputs {
49                results.extend(extract(input, selector)?);
50            }
51            Ok(results)
52        }
53        PipeStage::Builtin(builtin) => {
54            let mut results = Vec::new();
55            for input in inputs {
56                results.push(apply_builtin(builtin, input)?);
57            }
58            Ok(results)
59        }
60        PipeStage::Select(filter) => {
61            let mut results = Vec::new();
62            for input in inputs {
63                if super::filter::evaluate(input, filter)? {
64                    results.push(input.clone());
65                }
66            }
67            Ok(results)
68        }
69        PipeStage::Set { path, value } => {
70            let json_value = value.to_json_value();
71            let mut results = Vec::new();
72            for input in inputs {
73                results.push(super::manipulate::apply_set(input, &path.segments, &json_value)?);
74            }
75            Ok(results)
76        }
77        PipeStage::Del(path) => {
78            let mut results = Vec::new();
79            for input in inputs {
80                results.push(super::manipulate::apply_del(input, &path.segments)?);
81            }
82            Ok(results)
83        }
84    }
85}
86
87// ──────────────────────────────────────────────
88// Core extraction (path traversal)
89// ──────────────────────────────────────────────
90
91/// Extract values from a JSON value using a path selector.
92pub fn extract(value: &Value, selector: &Selector) -> Result<Vec<Value>, PickError> {
93    if selector.segments.is_empty() {
94        return Ok(vec![value.clone()]);
95    }
96
97    let mut current = vec![value.clone()];
98
99    for segment in &selector.segments {
100        let mut next = Vec::new();
101
102        for val in &current {
103            let keyed = resolve_key(val, segment)?;
104            let indexed = apply_indices(keyed, &segment.indices)?;
105            let final_values = apply_segment_builtin(&segment.builtin, indexed)?;
106
107            next.extend(final_values);
108            if next.len() > MAX_EXTRACT_RESULTS {
109                return Err(PickError::TooManyResults(MAX_EXTRACT_RESULTS));
110            }
111        }
112
113        current = next;
114    }
115
116    Ok(current)
117}
118
119// ──────────────────────────────────────────────
120// Key resolution (direct or recursive)
121// ──────────────────────────────────────────────
122
123fn resolve_key(value: &Value, segment: &Segment) -> Result<Vec<Value>, PickError> {
124    // Builtin-only segment (no key, no indices)
125    if segment.key.is_none() && segment.builtin.is_some() {
126        return Ok(vec![value.clone()]);
127    }
128
129    if segment.recursive {
130        resolve_key_recursive(value, segment)
131    } else {
132        resolve_key_direct(value, segment)
133    }
134}
135
136fn resolve_key_direct(value: &Value, segment: &Segment) -> Result<Vec<Value>, PickError> {
137    if let Some(ref key) = segment.key {
138        match value {
139            Value::Object(map) => match map.get(key) {
140                Some(v) => Ok(vec![v.clone()]),
141                None => Err(PickError::KeyNotFound(key.clone())),
142            },
143            other => Err(PickError::NotAnObject(
144                key.clone(),
145                value_type_name(other).into(),
146            )),
147        }
148    } else {
149        // No key — pass value through for index-only segments like [0]
150        Ok(vec![value.clone()])
151    }
152}
153
154fn resolve_key_recursive(value: &Value, segment: &Segment) -> Result<Vec<Value>, PickError> {
155    let key = segment.key.as_ref().ok_or_else(|| {
156        PickError::InvalidSelector("recursive descent requires a key".into())
157    })?;
158
159    let found = recursive_find(value, key);
160    if found.is_empty() {
161        return Err(PickError::KeyNotFound(key.clone()));
162    }
163    Ok(found)
164}
165
166/// DFS search for all occurrences of `key` anywhere in the value tree.
167/// Time: O(N) where N = total nodes. Space: O(d) stack + O(r) results.
168fn recursive_find(value: &Value, key: &str) -> Vec<Value> {
169    let mut results = Vec::new();
170    recursive_find_inner(value, key, &mut results);
171    results
172}
173
174fn recursive_find_inner(value: &Value, key: &str, results: &mut Vec<Value>) {
175    match value {
176        Value::Object(map) => {
177            if let Some(v) = map.get(key) {
178                results.push(v.clone());
179            }
180            for v in map.values() {
181                recursive_find_inner(v, key, results);
182            }
183        }
184        Value::Array(arr) => {
185            for item in arr {
186                recursive_find_inner(item, key, results);
187            }
188        }
189        _ => {}
190    }
191}
192
193// ──────────────────────────────────────────────
194// Index application (Number, Wildcard, Slice)
195// ──────────────────────────────────────────────
196
197fn apply_indices(values: Vec<Value>, indices: &[Index]) -> Result<Vec<Value>, PickError> {
198    let mut current = values;
199
200    for index in indices {
201        let mut next = Vec::new();
202        for v in &current {
203            match index {
204                Index::Number(n) => {
205                    apply_number_index(v, *n, &mut next)?;
206                }
207                Index::Wildcard => {
208                    apply_wildcard(v, &mut next)?;
209                }
210                Index::Slice { start, end } => {
211                    apply_slice(v, *start, *end, &mut next)?;
212                }
213            }
214        }
215        current = next;
216    }
217
218    Ok(current)
219}
220
221fn apply_number_index(value: &Value, n: i64, out: &mut Vec<Value>) -> Result<(), PickError> {
222    match value {
223        Value::Array(arr) => {
224            let i = resolve_array_index(n, arr.len())?;
225            match arr.get(i) {
226                Some(elem) => {
227                    out.push(elem.clone());
228                    Ok(())
229                }
230                None => Err(PickError::IndexOutOfBounds(n)),
231            }
232        }
233        other => Err(PickError::NotAnArray(value_type_name(other).into())),
234    }
235}
236
237fn apply_wildcard(value: &Value, out: &mut Vec<Value>) -> Result<(), PickError> {
238    match value {
239        Value::Array(arr) => {
240            out.extend(arr.iter().cloned());
241            Ok(())
242        }
243        other => Err(PickError::NotAnArray(value_type_name(other).into())),
244    }
245}
246
247/// Apply array slicing. Produces elements in range [start, end).
248/// Negative indices count from the end. Missing bounds default to
249/// 0 (start) or len (end). Out-of-range bounds are clamped.
250fn apply_slice(
251    value: &Value,
252    start: Option<i64>,
253    end: Option<i64>,
254    out: &mut Vec<Value>,
255) -> Result<(), PickError> {
256    match value {
257        Value::Array(arr) => {
258            let len = arr.len() as i64;
259            let s = resolve_slice_bound(start, 0, len);
260            let e = resolve_slice_bound(end, len, len);
261            let s = s.clamp(0, len) as usize;
262            let e = e.clamp(0, len) as usize;
263            if s < e {
264                out.extend(arr[s..e].iter().cloned());
265            }
266            Ok(())
267        }
268        other => Err(PickError::NotAnArray(value_type_name(other).into())),
269    }
270}
271
272fn resolve_array_index(n: i64, len: usize) -> Result<usize, PickError> {
273    let len_i64 = i64::try_from(len).map_err(|_| PickError::IndexOutOfBounds(n))?;
274    if n < 0 {
275        if n.unsigned_abs() > len as u64 {
276            return Err(PickError::IndexOutOfBounds(n));
277        }
278        Ok((len_i64 + n) as usize)
279    } else {
280        Ok(n as usize)
281    }
282}
283
284/// Resolve a slice bound, handling negative indices and defaults.
285fn resolve_slice_bound(bound: Option<i64>, default: i64, len: i64) -> i64 {
286    match bound {
287        None => default,
288        Some(i) if i < 0 => (len + i).max(0),
289        Some(i) => i,
290    }
291}
292
293// ──────────────────────────────────────────────
294// Builtin application
295// ──────────────────────────────────────────────
296
297fn apply_segment_builtin(
298    builtin: &Option<Builtin>,
299    values: Vec<Value>,
300) -> Result<Vec<Value>, PickError> {
301    match builtin {
302        None => Ok(values),
303        Some(b) => values
304            .into_iter()
305            .map(|v| apply_builtin(b, &v))
306            .collect(),
307    }
308}
309
310pub fn apply_builtin(builtin: &Builtin, value: &Value) -> Result<Value, PickError> {
311    match builtin {
312        Builtin::Keys => match value {
313            Value::Object(map) => Ok(Value::Array(
314                map.keys().map(|k| Value::String(k.clone())).collect(),
315            )),
316            Value::Array(arr) => Ok(Value::Array(
317                (0..arr.len())
318                    .map(|i| Value::Number(serde_json::Number::from(i)))
319                    .collect(),
320            )),
321            other => Err(PickError::InvalidSelector(format!(
322                "keys() requires object or array, got {}",
323                value_type_name(other)
324            ))),
325        },
326        Builtin::Values => match value {
327            Value::Object(map) => Ok(Value::Array(map.values().cloned().collect())),
328            Value::Array(_) => Ok(value.clone()),
329            other => Err(PickError::InvalidSelector(format!(
330                "values() requires object or array, got {}",
331                value_type_name(other)
332            ))),
333        },
334        Builtin::Length => match value {
335            Value::Array(arr) => Ok(Value::Number(arr.len().into())),
336            Value::Object(map) => Ok(Value::Number(map.len().into())),
337            Value::String(s) => Ok(Value::Number(s.len().into())),
338            Value::Null => Ok(Value::Number(0.into())),
339            other => Err(PickError::InvalidSelector(format!(
340                "length() requires array, object, or string, got {}",
341                value_type_name(other)
342            ))),
343        },
344    }
345}
346
347// ──────────────────────────────────────────────
348// Helpers
349// ──────────────────────────────────────────────
350
351pub fn value_type_name(v: &Value) -> &'static str {
352    match v {
353        Value::Null => "null",
354        Value::Bool(_) => "boolean",
355        Value::Number(_) => "number",
356        Value::String(_) => "string",
357        Value::Array(_) => "array",
358        Value::Object(_) => "object",
359    }
360}
361
362// ──────────────────────────────────────────────
363// Tests
364// ──────────────────────────────────────────────
365
366#[cfg(test)]
367mod tests {
368    use super::*;
369    use serde_json::json;
370
371    // ── Existing extraction tests (backward compatibility) ──
372
373    #[test]
374    fn extract_empty_selector() {
375        let val = json!({"a": 1});
376        let sel = Selector::parse("").unwrap();
377        let result = extract(&val, &sel).unwrap();
378        assert_eq!(result, vec![json!({"a": 1})]);
379    }
380
381    #[test]
382    fn extract_simple_key() {
383        let val = json!({"name": "Alice"});
384        let sel = Selector::parse("name").unwrap();
385        let result = extract(&val, &sel).unwrap();
386        assert_eq!(result, vec![json!("Alice")]);
387    }
388
389    #[test]
390    fn extract_nested_key() {
391        let val = json!({"foo": {"bar": 42}});
392        let sel = Selector::parse("foo.bar").unwrap();
393        let result = extract(&val, &sel).unwrap();
394        assert_eq!(result, vec![json!(42)]);
395    }
396
397    #[test]
398    fn extract_array_index() {
399        let val = json!({"items": [10, 20, 30]});
400        let sel = Selector::parse("items[1]").unwrap();
401        let result = extract(&val, &sel).unwrap();
402        assert_eq!(result, vec![json!(20)]);
403    }
404
405    #[test]
406    fn extract_negative_index() {
407        let val = json!({"items": [10, 20, 30]});
408        let sel = Selector::parse("items[-1]").unwrap();
409        let result = extract(&val, &sel).unwrap();
410        assert_eq!(result, vec![json!(30)]);
411    }
412
413    #[test]
414    fn extract_negative_index_first() {
415        let val = json!({"items": [10, 20, 30]});
416        let sel = Selector::parse("items[-3]").unwrap();
417        let result = extract(&val, &sel).unwrap();
418        assert_eq!(result, vec![json!(10)]);
419    }
420
421    #[test]
422    fn extract_wildcard() {
423        let val = json!({"items": [{"name": "a"}, {"name": "b"}]});
424        let sel = Selector::parse("items[*].name").unwrap();
425        let result = extract(&val, &sel).unwrap();
426        assert_eq!(result, vec![json!("a"), json!("b")]);
427    }
428
429    #[test]
430    fn extract_chained_indices() {
431        let val = json!({"matrix": [[1, 2], [3, 4]]});
432        let sel = Selector::parse("matrix[0][1]").unwrap();
433        let result = extract(&val, &sel).unwrap();
434        assert_eq!(result, vec![json!(2)]);
435    }
436
437    #[test]
438    fn extract_leading_index() {
439        let val = json!([{"name": "first"}, {"name": "second"}]);
440        let sel = Selector::parse("[0].name").unwrap();
441        let result = extract(&val, &sel).unwrap();
442        assert_eq!(result, vec![json!("first")]);
443    }
444
445    #[test]
446    fn extract_key_not_found() {
447        let val = json!({"a": 1});
448        let sel = Selector::parse("b").unwrap();
449        assert!(extract(&val, &sel).is_err());
450    }
451
452    #[test]
453    fn extract_index_out_of_bounds() {
454        let val = json!({"items": [1, 2]});
455        let sel = Selector::parse("items[5]").unwrap();
456        assert!(extract(&val, &sel).is_err());
457    }
458
459    #[test]
460    fn extract_negative_index_out_of_bounds() {
461        let val = json!({"items": [1, 2]});
462        let sel = Selector::parse("items[-5]").unwrap();
463        assert!(extract(&val, &sel).is_err());
464    }
465
466    #[test]
467    fn extract_not_an_object() {
468        let val = json!("hello");
469        let sel = Selector::parse("foo").unwrap();
470        assert!(extract(&val, &sel).is_err());
471    }
472
473    #[test]
474    fn extract_not_an_array() {
475        let val = json!({"foo": "bar"});
476        let sel = Selector::parse("foo[0]").unwrap();
477        assert!(extract(&val, &sel).is_err());
478    }
479
480    #[test]
481    fn extract_wildcard_on_non_array() {
482        let val = json!({"foo": "bar"});
483        let sel = Selector::parse("foo[*]").unwrap();
484        assert!(extract(&val, &sel).is_err());
485    }
486
487    #[test]
488    fn extract_null_value() {
489        let val = json!({"foo": null});
490        let sel = Selector::parse("foo").unwrap();
491        let result = extract(&val, &sel).unwrap();
492        assert_eq!(result, vec![Value::Null]);
493    }
494
495    #[test]
496    fn extract_boolean() {
497        let val = json!({"active": true});
498        let sel = Selector::parse("active").unwrap();
499        let result = extract(&val, &sel).unwrap();
500        assert_eq!(result, vec![json!(true)]);
501    }
502
503    #[test]
504    fn extract_nested_array_wildcard() {
505        let val = json!([{"items": [1, 2]}, {"items": [3, 4]}]);
506        let sel = Selector::parse("[*].items[0]").unwrap();
507        let result = extract(&val, &sel).unwrap();
508        assert_eq!(result, vec![json!(1), json!(3)]);
509    }
510
511    #[test]
512    fn extract_deep_nesting() {
513        let val = json!({"a": {"b": {"c": {"d": 99}}}});
514        let sel = Selector::parse("a.b.c.d").unwrap();
515        let result = extract(&val, &sel).unwrap();
516        assert_eq!(result, vec![json!(99)]);
517    }
518
519    #[test]
520    fn extract_key_on_null() {
521        let val = json!({"a": null});
522        let sel = Selector::parse("a.b").unwrap();
523        assert!(extract(&val, &sel).is_err());
524    }
525
526    #[test]
527    fn extract_quoted_key_with_dot() {
528        let val = json!({"foo.bar": {"baz": 1}});
529        let sel = Selector::parse("\"foo.bar\".baz").unwrap();
530        let result = extract(&val, &sel).unwrap();
531        assert_eq!(result, vec![json!(1)]);
532    }
533
534    #[test]
535    fn extract_hyphenated_key() {
536        let val = json!({"content-type": "text/html"});
537        let sel = Selector::parse("content-type").unwrap();
538        let result = extract(&val, &sel).unwrap();
539        assert_eq!(result, vec![json!("text/html")]);
540    }
541
542    #[test]
543    fn extract_empty_array_wildcard() {
544        let val = json!({"items": []});
545        let sel = Selector::parse("items[*]").unwrap();
546        let result = extract(&val, &sel).unwrap();
547        assert!(result.is_empty());
548    }
549
550    // ── Phase 1: Slice extraction ──
551
552    #[test]
553    fn extract_slice_full() {
554        let val = json!({"items": [10, 20, 30, 40, 50]});
555        let sel = Selector::parse("items[1:3]").unwrap();
556        let result = extract(&val, &sel).unwrap();
557        assert_eq!(result, vec![json!(20), json!(30)]);
558    }
559
560    #[test]
561    fn extract_slice_from_start() {
562        let val = json!({"items": [10, 20, 30, 40, 50]});
563        let sel = Selector::parse("items[:2]").unwrap();
564        let result = extract(&val, &sel).unwrap();
565        assert_eq!(result, vec![json!(10), json!(20)]);
566    }
567
568    #[test]
569    fn extract_slice_to_end() {
570        let val = json!({"items": [10, 20, 30, 40, 50]});
571        let sel = Selector::parse("items[3:]").unwrap();
572        let result = extract(&val, &sel).unwrap();
573        assert_eq!(result, vec![json!(40), json!(50)]);
574    }
575
576    #[test]
577    fn extract_slice_all() {
578        let val = json!({"items": [10, 20, 30]});
579        let sel = Selector::parse("items[:]").unwrap();
580        let result = extract(&val, &sel).unwrap();
581        assert_eq!(result, vec![json!(10), json!(20), json!(30)]);
582    }
583
584    #[test]
585    fn extract_slice_negative_start() {
586        let val = json!({"items": [10, 20, 30, 40, 50]});
587        let sel = Selector::parse("items[-2:]").unwrap();
588        let result = extract(&val, &sel).unwrap();
589        assert_eq!(result, vec![json!(40), json!(50)]);
590    }
591
592    #[test]
593    fn extract_slice_negative_end() {
594        let val = json!({"items": [10, 20, 30, 40, 50]});
595        let sel = Selector::parse("items[:-2]").unwrap();
596        let result = extract(&val, &sel).unwrap();
597        assert_eq!(result, vec![json!(10), json!(20), json!(30)]);
598    }
599
600    #[test]
601    fn extract_slice_both_negative() {
602        let val = json!({"items": [10, 20, 30, 40, 50]});
603        let sel = Selector::parse("items[-3:-1]").unwrap();
604        let result = extract(&val, &sel).unwrap();
605        assert_eq!(result, vec![json!(30), json!(40)]);
606    }
607
608    #[test]
609    fn extract_slice_empty_result() {
610        let val = json!({"items": [10, 20, 30]});
611        let sel = Selector::parse("items[5:10]").unwrap();
612        let result = extract(&val, &sel).unwrap();
613        assert!(result.is_empty());
614    }
615
616    #[test]
617    fn extract_slice_reversed_bounds_empty() {
618        let val = json!({"items": [10, 20, 30]});
619        let sel = Selector::parse("items[3:1]").unwrap();
620        let result = extract(&val, &sel).unwrap();
621        assert!(result.is_empty());
622    }
623
624    #[test]
625    fn extract_slice_on_non_array() {
626        let val = json!({"items": "hello"});
627        let sel = Selector::parse("items[0:2]").unwrap();
628        assert!(extract(&val, &sel).is_err());
629    }
630
631    #[test]
632    fn extract_slice_clamped_end() {
633        // End beyond array length should be clamped
634        let val = json!({"items": [10, 20, 30]});
635        let sel = Selector::parse("items[1:100]").unwrap();
636        let result = extract(&val, &sel).unwrap();
637        assert_eq!(result, vec![json!(20), json!(30)]);
638    }
639
640    #[test]
641    fn extract_slice_chained_with_index() {
642        let val = json!({"m": [[1, 2, 3], [4, 5, 6]]});
643        let sel = Selector::parse("m[0][1:3]").unwrap();
644        let result = extract(&val, &sel).unwrap();
645        assert_eq!(result, vec![json!(2), json!(3)]);
646    }
647
648    // ── Phase 1: Builtin extraction ──
649
650    #[test]
651    fn extract_keys_object() {
652        let val = json!({"b": 2, "a": 1});
653        let sel = Selector::parse("keys()").unwrap();
654        let result = extract(&val, &sel).unwrap();
655        // serde_json preserves insertion order
656        let keys = &result[0];
657        assert!(keys.is_array());
658        let arr = keys.as_array().unwrap();
659        assert!(arr.contains(&json!("a")));
660        assert!(arr.contains(&json!("b")));
661    }
662
663    #[test]
664    fn extract_keys_array() {
665        let val = json!([10, 20, 30]);
666        let sel = Selector::parse("keys()").unwrap();
667        let result = extract(&val, &sel).unwrap();
668        assert_eq!(result, vec![json!([0, 1, 2])]);
669    }
670
671    #[test]
672    fn extract_values_object() {
673        let val = json!({"a": 1, "b": 2});
674        let sel = Selector::parse("values()").unwrap();
675        let result = extract(&val, &sel).unwrap();
676        let arr = result[0].as_array().unwrap();
677        assert!(arr.contains(&json!(1)));
678        assert!(arr.contains(&json!(2)));
679    }
680
681    #[test]
682    fn extract_length_array() {
683        let val = json!({"items": [1, 2, 3]});
684        let sel = Selector::parse("items.length()").unwrap();
685        let result = extract(&val, &sel).unwrap();
686        assert_eq!(result, vec![json!(3)]);
687    }
688
689    #[test]
690    fn extract_length_object() {
691        let val = json!({"a": 1, "b": 2, "c": 3});
692        let sel = Selector::parse("length()").unwrap();
693        let result = extract(&val, &sel).unwrap();
694        assert_eq!(result, vec![json!(3)]);
695    }
696
697    #[test]
698    fn extract_length_string() {
699        let val = json!({"name": "Alice"});
700        let sel = Selector::parse("name.length()").unwrap();
701        let result = extract(&val, &sel).unwrap();
702        assert_eq!(result, vec![json!(5)]);
703    }
704
705    #[test]
706    fn extract_length_null() {
707        let val = json!(null);
708        let sel = Selector::parse("length()").unwrap();
709        let result = extract(&val, &sel).unwrap();
710        assert_eq!(result, vec![json!(0)]);
711    }
712
713    #[test]
714    fn extract_keys_after_path() {
715        let val = json!({"data": {"x": 1, "y": 2}});
716        let sel = Selector::parse("data.keys()").unwrap();
717        let result = extract(&val, &sel).unwrap();
718        let arr = result[0].as_array().unwrap();
719        assert!(arr.contains(&json!("x")));
720        assert!(arr.contains(&json!("y")));
721    }
722
723    #[test]
724    fn extract_keys_on_string_error() {
725        let val = json!("hello");
726        let sel = Selector::parse("keys()").unwrap();
727        assert!(extract(&val, &sel).is_err());
728    }
729
730    #[test]
731    fn extract_length_on_number_error() {
732        let val = json!(42);
733        let sel = Selector::parse("length()").unwrap();
734        assert!(extract(&val, &sel).is_err());
735    }
736
737    // ── Phase 1: Recursive descent extraction ──
738
739    #[test]
740    fn extract_recursive_simple() {
741        let val = json!({"a": {"b": {"name": "deep"}}});
742        let sel = Selector::parse("..name").unwrap();
743        let result = extract(&val, &sel).unwrap();
744        assert_eq!(result, vec![json!("deep")]);
745    }
746
747    #[test]
748    fn extract_recursive_multiple_matches() {
749        let val = json!({
750            "users": [
751                {"name": "Alice", "address": {"name": "Home"}},
752                {"name": "Bob"}
753            ]
754        });
755        let sel = Selector::parse("..name").unwrap();
756        let result = extract(&val, &sel).unwrap();
757        assert!(result.contains(&json!("Alice")));
758        assert!(result.contains(&json!("Home")));
759        assert!(result.contains(&json!("Bob")));
760        assert_eq!(result.len(), 3);
761    }
762
763    #[test]
764    fn extract_recursive_after_key() {
765        let val = json!({
766            "data": {
767                "nested": {"id": 1},
768                "deep": {"nested": {"id": 2}}
769            }
770        });
771        let sel = Selector::parse("data..id").unwrap();
772        let result = extract(&val, &sel).unwrap();
773        assert!(result.contains(&json!(1)));
774        assert!(result.contains(&json!(2)));
775    }
776
777    #[test]
778    fn extract_recursive_with_index() {
779        let val = json!({
780            "a": {"items": [10, 20]},
781            "b": {"items": [30, 40]}
782        });
783        let sel = Selector::parse("..items[0]").unwrap();
784        let result = extract(&val, &sel).unwrap();
785        assert!(result.contains(&json!(10)));
786        assert!(result.contains(&json!(30)));
787    }
788
789    #[test]
790    fn extract_recursive_not_found() {
791        let val = json!({"a": 1, "b": 2});
792        let sel = Selector::parse("..missing").unwrap();
793        assert!(extract(&val, &sel).is_err());
794    }
795
796    #[test]
797    fn extract_recursive_in_array() {
798        let val = json!([
799            {"id": 1, "children": [{"id": 2}]},
800            {"id": 3}
801        ]);
802        let sel = Selector::parse("..id").unwrap();
803        let result = extract(&val, &sel).unwrap();
804        assert_eq!(result, vec![json!(1), json!(2), json!(3)]);
805    }
806
807    // ── Phase 1: Expression (multi-selector) execution ──
808
809    #[test]
810    fn execute_single_selector() {
811        let val = json!({"name": "Alice", "age": 30});
812        let expr = Expression::parse("name").unwrap();
813        let result = execute(&val, &expr).unwrap();
814        assert_eq!(result, vec![json!("Alice")]);
815    }
816
817    #[test]
818    fn execute_multiple_selectors() {
819        let val = json!({"name": "Alice", "age": 30});
820        let expr = Expression::parse("name, age").unwrap();
821        let result = execute(&val, &expr).unwrap();
822        assert_eq!(result, vec![json!("Alice"), json!(30)]);
823    }
824
825    #[test]
826    fn execute_multi_selector_missing_one() {
827        let val = json!({"name": "Alice"});
828        let expr = Expression::parse("name, missing").unwrap();
829        let result = execute(&val, &expr).unwrap();
830        assert_eq!(result, vec![json!("Alice")]);
831    }
832
833    #[test]
834    fn execute_single_selector_missing_errors() {
835        let val = json!({"name": "Alice"});
836        let expr = Expression::parse("missing").unwrap();
837        assert!(execute(&val, &expr).is_err());
838    }
839
840    // ── Phase 2: Pipeline execution ──
841
842    #[test]
843    fn execute_pipeline_simple_path() {
844        let val = json!({"items": [1, 2, 3]});
845        let expr = Expression::parse("items[0]").unwrap();
846        let result = execute(&val, &expr).unwrap();
847        assert_eq!(result, vec![json!(1)]);
848    }
849
850    #[test]
851    fn execute_pipeline_with_builtin() {
852        let val = json!({"data": {"x": 1, "y": 2}});
853        let expr = Expression::parse("data | keys()").unwrap();
854        let result = execute(&val, &expr).unwrap();
855        let arr = result[0].as_array().unwrap();
856        assert!(arr.contains(&json!("x")));
857        assert!(arr.contains(&json!("y")));
858    }
859
860    #[test]
861    fn execute_pipeline_with_length() {
862        let val = json!({"items": [1, 2, 3, 4, 5]});
863        let expr = Expression::parse("items | length()").unwrap();
864        let result = execute(&val, &expr).unwrap();
865        assert_eq!(result, vec![json!(5)]);
866    }
867
868    #[test]
869    fn execute_pipeline_select_filter() {
870        let val = json!({"items": [
871            {"name": "a", "price": 50},
872            {"name": "b", "price": 150},
873            {"name": "c", "price": 200}
874        ]});
875        let expr = Expression::parse("items[*] | select(.price > 100)").unwrap();
876        let result = execute(&val, &expr).unwrap();
877        assert_eq!(result.len(), 2);
878        assert_eq!(result[0]["name"], json!("b"));
879        assert_eq!(result[1]["name"], json!("c"));
880    }
881
882    #[test]
883    fn execute_pipeline_select_then_path() {
884        let val = json!({"items": [
885            {"name": "a", "price": 50},
886            {"name": "b", "price": 150}
887        ]});
888        let expr = Expression::parse("items[*] | select(.price > 100) | name").unwrap();
889        let result = execute(&val, &expr).unwrap();
890        assert_eq!(result, vec![json!("b")]);
891    }
892
893    #[test]
894    fn execute_pipeline_select_eq_string() {
895        let val = json!({"users": [
896            {"name": "Alice", "role": "admin"},
897            {"name": "Bob", "role": "user"}
898        ]});
899        let expr = Expression::parse("users[*] | select(.role == \"admin\")").unwrap();
900        let result = execute(&val, &expr).unwrap();
901        assert_eq!(result.len(), 1);
902        assert_eq!(result[0]["name"], json!("Alice"));
903    }
904
905    #[test]
906    fn execute_pipeline_select_regex() {
907        let val = json!({"items": [
908            {"name": "apple"},
909            {"name": "banana"},
910            {"name": "avocado"}
911        ]});
912        let expr = Expression::parse("items[*] | select(.name ~ \"^a\")").unwrap();
913        let result = execute(&val, &expr).unwrap();
914        assert_eq!(result.len(), 2);
915    }
916
917    #[test]
918    fn execute_pipeline_select_truthy() {
919        let val = json!({"items": [
920            {"name": "a", "active": true},
921            {"name": "b", "active": false},
922            {"name": "c", "active": true}
923        ]});
924        let expr = Expression::parse("items[*] | select(.active)").unwrap();
925        let result = execute(&val, &expr).unwrap();
926        assert_eq!(result.len(), 2);
927    }
928
929    #[test]
930    fn execute_pipeline_select_not_truthy() {
931        let val = json!({"items": [
932            {"name": "a", "active": true},
933            {"name": "b", "active": false}
934        ]});
935        let expr = Expression::parse("items[*] | select(not .active)").unwrap();
936        let result = execute(&val, &expr).unwrap();
937        assert_eq!(result.len(), 1);
938        assert_eq!(result[0]["name"], json!("b"));
939    }
940
941    #[test]
942    fn execute_pipeline_select_and() {
943        let val = json!({"items": [
944            {"price": 50, "stock": 10},
945            {"price": 150, "stock": 0},
946            {"price": 200, "stock": 5}
947        ]});
948        let expr =
949            Expression::parse("items[*] | select(.price > 100 and .stock > 0)").unwrap();
950        let result = execute(&val, &expr).unwrap();
951        assert_eq!(result.len(), 1);
952        assert_eq!(result[0]["price"], json!(200));
953    }
954
955    #[test]
956    fn execute_pipeline_select_or() {
957        let val = json!({"items": [
958            {"price": 5, "featured": true},
959            {"price": 50, "featured": false},
960            {"price": 500, "featured": false}
961        ]});
962        let expr =
963            Expression::parse("items[*] | select(.price > 100 or .featured == true)").unwrap();
964        let result = execute(&val, &expr).unwrap();
965        assert_eq!(result.len(), 2);
966    }
967
968    #[test]
969    fn execute_pipeline_select_identity() {
970        // select(. > 5) on a flat array
971        let val = json!([1, 3, 5, 7, 9]);
972        let expr = Expression::parse("[*] | select(. > 5)").unwrap();
973        let result = execute(&val, &expr).unwrap();
974        assert_eq!(result, vec![json!(7), json!(9)]);
975    }
976
977    #[test]
978    fn execute_pipeline_select_lte() {
979        let val = json!([10, 20, 30, 40, 50]);
980        let expr = Expression::parse("[*] | select(. <= 30)").unwrap();
981        let result = execute(&val, &expr).unwrap();
982        assert_eq!(result, vec![json!(10), json!(20), json!(30)]);
983    }
984
985    #[test]
986    fn execute_pipeline_select_ne() {
987        let val = json!({"items": [
988            {"status": "active"},
989            {"status": "deleted"},
990            {"status": "active"}
991        ]});
992        let expr =
993            Expression::parse("items[*] | select(.status != \"deleted\")").unwrap();
994        let result = execute(&val, &expr).unwrap();
995        assert_eq!(result.len(), 2);
996    }
997
998    #[test]
999    fn execute_pipeline_select_null_check() {
1000        let val = json!({"items": [
1001            {"name": "a", "email": null},
1002            {"name": "b", "email": "b@x.com"}
1003        ]});
1004        let expr =
1005            Expression::parse("items[*] | select(.email != null)").unwrap();
1006        let result = execute(&val, &expr).unwrap();
1007        assert_eq!(result.len(), 1);
1008        assert_eq!(result[0]["name"], json!("b"));
1009    }
1010
1011    // ── Phase 3: set / del execution ──
1012
1013    #[test]
1014    fn execute_set_simple() {
1015        let val = json!({"name": "Alice", "age": 30});
1016        let expr = Expression::parse("set(.name, \"Bob\")").unwrap();
1017        let result = execute(&val, &expr).unwrap();
1018        assert_eq!(result[0]["name"], json!("Bob"));
1019        assert_eq!(result[0]["age"], json!(30));
1020    }
1021
1022    #[test]
1023    fn execute_set_nested() {
1024        let val = json!({"user": {"name": "Alice", "age": 30}});
1025        let expr = Expression::parse("set(.user.name, \"Bob\")").unwrap();
1026        let result = execute(&val, &expr).unwrap();
1027        assert_eq!(result[0]["user"]["name"], json!("Bob"));
1028        assert_eq!(result[0]["user"]["age"], json!(30));
1029    }
1030
1031    #[test]
1032    fn execute_set_number() {
1033        let val = json!({"count": 0});
1034        let expr = Expression::parse("set(.count, 42)").unwrap();
1035        let result = execute(&val, &expr).unwrap();
1036        assert_eq!(result[0]["count"], json!(42));
1037    }
1038
1039    #[test]
1040    fn execute_set_bool() {
1041        let val = json!({"active": false});
1042        let expr = Expression::parse("set(.active, true)").unwrap();
1043        let result = execute(&val, &expr).unwrap();
1044        assert_eq!(result[0]["active"], json!(true));
1045    }
1046
1047    #[test]
1048    fn execute_set_null() {
1049        let val = json!({"temp": "data"});
1050        let expr = Expression::parse("set(.temp, null)").unwrap();
1051        let result = execute(&val, &expr).unwrap();
1052        assert_eq!(result[0]["temp"], json!(null));
1053    }
1054
1055    #[test]
1056    fn execute_set_new_key() {
1057        let val = json!({"a": 1});
1058        let expr = Expression::parse("set(.b, 2)").unwrap();
1059        let result = execute(&val, &expr).unwrap();
1060        assert_eq!(result[0]["a"], json!(1));
1061        assert_eq!(result[0]["b"], json!(2));
1062    }
1063
1064    #[test]
1065    fn execute_set_array_index() {
1066        let val = json!({"items": [1, 2, 3]});
1067        let expr = Expression::parse("set(.items[1], 99)").unwrap();
1068        let result = execute(&val, &expr).unwrap();
1069        assert_eq!(result[0]["items"], json!([1, 99, 3]));
1070    }
1071
1072    #[test]
1073    fn execute_del_simple() {
1074        let val = json!({"name": "Alice", "temp": "data"});
1075        let expr = Expression::parse("del(.temp)").unwrap();
1076        let result = execute(&val, &expr).unwrap();
1077        assert_eq!(result[0], json!({"name": "Alice"}));
1078    }
1079
1080    #[test]
1081    fn execute_del_nested() {
1082        let val = json!({"user": {"name": "Alice", "temp": "x"}});
1083        let expr = Expression::parse("del(.user.temp)").unwrap();
1084        let result = execute(&val, &expr).unwrap();
1085        assert_eq!(result[0], json!({"user": {"name": "Alice"}}));
1086    }
1087
1088    #[test]
1089    fn execute_del_array_element() {
1090        let val = json!({"items": [1, 2, 3]});
1091        let expr = Expression::parse("del(.items[1])").unwrap();
1092        let result = execute(&val, &expr).unwrap();
1093        assert_eq!(result[0]["items"], json!([1, 3]));
1094    }
1095
1096    #[test]
1097    fn execute_del_missing_key() {
1098        // Deleting a non-existent key is a no-op
1099        let val = json!({"a": 1});
1100        let expr = Expression::parse("del(.missing)").unwrap();
1101        let result = execute(&val, &expr).unwrap();
1102        assert_eq!(result[0], json!({"a": 1}));
1103    }
1104
1105    #[test]
1106    fn execute_set_then_extract() {
1107        let val = json!({"name": "Alice"});
1108        // Pipeline: set then extract
1109        let expr = Expression::parse("set(.name, \"Bob\") | name").unwrap();
1110        let result = execute(&val, &expr).unwrap();
1111        assert_eq!(result, vec![json!("Bob")]);
1112    }
1113
1114    #[test]
1115    fn execute_del_then_keys() {
1116        let val = json!({"a": 1, "b": 2, "c": 3});
1117        let expr = Expression::parse("del(.b) | keys()").unwrap();
1118        let result = execute(&val, &expr).unwrap();
1119        let arr = result[0].as_array().unwrap();
1120        assert!(arr.contains(&json!("a")));
1121        assert!(arr.contains(&json!("c")));
1122        assert!(!arr.contains(&json!("b")));
1123    }
1124
1125    // ── resolve_slice_bound ──
1126
1127    #[test]
1128    fn slice_bound_none_returns_default() {
1129        assert_eq!(resolve_slice_bound(None, 0, 5), 0);
1130        assert_eq!(resolve_slice_bound(None, 5, 5), 5);
1131    }
1132
1133    #[test]
1134    fn slice_bound_positive() {
1135        assert_eq!(resolve_slice_bound(Some(2), 0, 5), 2);
1136    }
1137
1138    #[test]
1139    fn slice_bound_negative() {
1140        assert_eq!(resolve_slice_bound(Some(-2), 0, 5), 3);
1141    }
1142
1143    #[test]
1144    fn slice_bound_negative_past_zero() {
1145        assert_eq!(resolve_slice_bound(Some(-10), 0, 5), 0);
1146    }
1147
1148    // ── apply_builtin ──
1149
1150    #[test]
1151    fn builtin_keys_empty_object() {
1152        let result = apply_builtin(&Builtin::Keys, &json!({})).unwrap();
1153        assert_eq!(result, json!([]));
1154    }
1155
1156    #[test]
1157    fn builtin_values_empty_object() {
1158        let result = apply_builtin(&Builtin::Values, &json!({})).unwrap();
1159        assert_eq!(result, json!([]));
1160    }
1161
1162    #[test]
1163    fn builtin_length_empty_array() {
1164        let result = apply_builtin(&Builtin::Length, &json!([])).unwrap();
1165        assert_eq!(result, json!(0));
1166    }
1167
1168    #[test]
1169    fn builtin_length_empty_string() {
1170        let result = apply_builtin(&Builtin::Length, &json!("")).unwrap();
1171        assert_eq!(result, json!(0));
1172    }
1173
1174    #[test]
1175    fn builtin_values_array_passthrough() {
1176        let result = apply_builtin(&Builtin::Values, &json!([1, 2])).unwrap();
1177        assert_eq!(result, json!([1, 2]));
1178    }
1179
1180    // ══════════════════════════════════════════════
1181    // Additional coverage tests
1182    // ══════════════════════════════════════════════
1183
1184    // ── Slice + other index combinations ──
1185
1186    #[test]
1187    fn extract_slice_deeply_nested() {
1188        let val = json!({"data": [{"items": [10, 20, 30, 40]}]});
1189        let sel = Selector::parse("data[0].items[1:3]").unwrap();
1190        let result = extract(&val, &sel).unwrap();
1191        assert_eq!(result, vec![json!(20), json!(30)]);
1192    }
1193
1194    #[test]
1195    fn extract_wildcard_then_slice() {
1196        let val = json!([[1, 2, 3], [4, 5, 6], [7, 8, 9]]);
1197        let sel = Selector::parse("[*][0:2]").unwrap();
1198        let result = extract(&val, &sel).unwrap();
1199        assert_eq!(result, vec![json!(1), json!(2), json!(4), json!(5), json!(7), json!(8)]);
1200    }
1201
1202    #[test]
1203    fn extract_slice_then_index() {
1204        let val = json!([[10, 20], [30, 40], [50, 60]]);
1205        let sel = Selector::parse("[0:2][0]").unwrap();
1206        let result = extract(&val, &sel).unwrap();
1207        assert_eq!(result, vec![json!(10), json!(30)]);
1208    }
1209
1210    #[test]
1211    fn extract_slice_zero_to_zero_empty() {
1212        let val = json!({"items": [1, 2, 3]});
1213        let sel = Selector::parse("items[0:0]").unwrap();
1214        let result = extract(&val, &sel).unwrap();
1215        assert!(result.is_empty());
1216    }
1217
1218    #[test]
1219    fn extract_slice_negative_out_of_bounds() {
1220        // items[-100:] on a 3-element array should clamp to [0:]
1221        let val = json!({"items": [1, 2, 3]});
1222        let sel = Selector::parse("items[-100:]").unwrap();
1223        let result = extract(&val, &sel).unwrap();
1224        assert_eq!(result, vec![json!(1), json!(2), json!(3)]);
1225    }
1226
1227    #[test]
1228    fn extract_slice_negative_end_out_of_bounds() {
1229        // items[:-100] should be empty (end clamps to 0)
1230        let val = json!({"items": [1, 2, 3]});
1231        let sel = Selector::parse("items[:-100]").unwrap();
1232        let result = extract(&val, &sel).unwrap();
1233        assert!(result.is_empty());
1234    }
1235
1236    #[test]
1237    fn extract_slice_single_element() {
1238        let val = json!([10, 20, 30]);
1239        let sel = Selector::parse("[1:2]").unwrap();
1240        let result = extract(&val, &sel).unwrap();
1241        assert_eq!(result, vec![json!(20)]);
1242    }
1243
1244    #[test]
1245    fn extract_triple_index_depth() {
1246        let val = json!([[[1, 2], [3, 4]], [[5, 6], [7, 8]]]);
1247        let sel = Selector::parse("[0][1][0]").unwrap();
1248        let result = extract(&val, &sel).unwrap();
1249        assert_eq!(result, vec![json!(3)]);
1250    }
1251
1252    #[test]
1253    fn extract_chained_wildcards() {
1254        let val = json!([[1, 2], [3, 4]]);
1255        let sel = Selector::parse("[*][*]").unwrap();
1256        let result = extract(&val, &sel).unwrap();
1257        assert_eq!(result, vec![json!(1), json!(2), json!(3), json!(4)]);
1258    }
1259
1260    // ── Builtin edge cases ──
1261
1262    #[test]
1263    fn extract_values_on_string_error() {
1264        let val = json!("hello");
1265        let sel = Selector::parse("values()").unwrap();
1266        assert!(extract(&val, &sel).is_err());
1267    }
1268
1269    #[test]
1270    fn extract_length_on_bool_error() {
1271        let val = json!(true);
1272        let sel = Selector::parse("length()").unwrap();
1273        assert!(extract(&val, &sel).is_err());
1274    }
1275
1276    #[test]
1277    fn extract_keys_on_null_error() {
1278        let val = json!(null);
1279        let sel = Selector::parse("keys()").unwrap();
1280        assert!(extract(&val, &sel).is_err());
1281    }
1282
1283    #[test]
1284    fn extract_builtin_on_wildcard_results() {
1285        // items[*].length() — each element gets length()
1286        let val = json!({"items": ["ab", "cde", "f"]});
1287        let sel = Selector::parse("items[*].length()").unwrap();
1288        let result = extract(&val, &sel).unwrap();
1289        assert_eq!(result, vec![json!(2), json!(3), json!(1)]);
1290    }
1291
1292    #[test]
1293    fn extract_keys_on_large_object() {
1294        let val = json!({"a": 1, "b": 2, "c": 3, "d": 4, "e": 5});
1295        let sel = Selector::parse("keys()").unwrap();
1296        let result = extract(&val, &sel).unwrap();
1297        assert_eq!(result[0].as_array().unwrap().len(), 5);
1298    }
1299
1300    // ── Recursive descent edge cases ──
1301
1302    #[test]
1303    fn extract_recursive_with_wildcard() {
1304        let val = json!({
1305            "a": {"items": [1, 2]},
1306            "b": {"items": [3, 4]}
1307        });
1308        let sel = Selector::parse("..items[*]").unwrap();
1309        let result = extract(&val, &sel).unwrap();
1310        assert!(result.contains(&json!(1)));
1311        assert!(result.contains(&json!(2)));
1312        assert!(result.contains(&json!(3)));
1313        assert!(result.contains(&json!(4)));
1314    }
1315
1316    #[test]
1317    fn extract_recursive_with_slice() {
1318        let val = json!({
1319            "a": {"items": [10, 20, 30]},
1320            "b": {"items": [40, 50, 60]}
1321        });
1322        let sel = Selector::parse("..items[0:2]").unwrap();
1323        let result = extract(&val, &sel).unwrap();
1324        assert!(result.contains(&json!(10)));
1325        assert!(result.contains(&json!(20)));
1326        assert!(result.contains(&json!(40)));
1327        assert!(result.contains(&json!(50)));
1328    }
1329
1330    #[test]
1331    fn extract_recursive_on_flat_value() {
1332        // No nesting, key at top level
1333        let val = json!({"name": "Alice"});
1334        let sel = Selector::parse("..name").unwrap();
1335        let result = extract(&val, &sel).unwrap();
1336        assert_eq!(result, vec![json!("Alice")]);
1337    }
1338
1339    #[test]
1340    fn extract_recursive_deeply_nested() {
1341        let val = json!({"a": {"b": {"c": {"d": {"target": 42}}}}});
1342        let sel = Selector::parse("..target").unwrap();
1343        let result = extract(&val, &sel).unwrap();
1344        assert_eq!(result, vec![json!(42)]);
1345    }
1346
1347    #[test]
1348    fn extract_recursive_in_mixed_arrays_and_objects() {
1349        let val = json!({
1350            "items": [
1351                {"id": 1, "sub": {"id": 10}},
1352                {"id": 2, "sub": [{"id": 20}, {"id": 21}]}
1353            ]
1354        });
1355        let sel = Selector::parse("..id").unwrap();
1356        let result = extract(&val, &sel).unwrap();
1357        assert!(result.contains(&json!(1)));
1358        assert!(result.contains(&json!(10)));
1359        assert!(result.contains(&json!(2)));
1360        assert!(result.contains(&json!(20)));
1361        assert!(result.contains(&json!(21)));
1362        assert_eq!(result.len(), 5);
1363    }
1364
1365    // ── Multi-selector edge cases ──
1366
1367    #[test]
1368    fn execute_multi_selector_both_missing() {
1369        let val = json!({"x": 1});
1370        let expr = Expression::parse("missing1, missing2").unwrap();
1371        let result = execute(&val, &expr).unwrap();
1372        assert!(result.is_empty());
1373    }
1374
1375    #[test]
1376    fn execute_multi_selector_with_array_paths() {
1377        let val = json!({"items": [1, 2, 3], "name": "test"});
1378        let expr = Expression::parse("items[0], name").unwrap();
1379        let result = execute(&val, &expr).unwrap();
1380        assert_eq!(result, vec![json!(1), json!("test")]);
1381    }
1382
1383    #[test]
1384    fn execute_multi_selector_with_nested() {
1385        let val = json!({"user": {"name": "Alice"}, "config": {"debug": true}});
1386        let expr = Expression::parse("user.name, config.debug").unwrap();
1387        let result = execute(&val, &expr).unwrap();
1388        assert_eq!(result, vec![json!("Alice"), json!(true)]);
1389    }
1390
1391    #[test]
1392    fn execute_multi_selector_same_key_twice() {
1393        let val = json!({"name": "Alice"});
1394        let expr = Expression::parse("name, name").unwrap();
1395        let result = execute(&val, &expr).unwrap();
1396        assert_eq!(result, vec![json!("Alice"), json!("Alice")]);
1397    }
1398
1399    // ── Pipeline 3+ stages ──
1400
1401    #[test]
1402    fn execute_pipeline_three_stages() {
1403        let val = json!({"items": [
1404            {"name": "a", "price": 50},
1405            {"name": "b", "price": 150},
1406            {"name": "c", "price": 200}
1407        ]});
1408        let expr = Expression::parse("items[*] | select(.price > 100) | name").unwrap();
1409        let result = execute(&val, &expr).unwrap();
1410        assert_eq!(result, vec![json!("b"), json!("c")]);
1411    }
1412
1413    #[test]
1414    fn execute_pipeline_four_stages() {
1415        let val = json!({"items": [
1416            {"name": "ab", "active": true},
1417            {"name": "cde", "active": false},
1418            {"name": "fgh", "active": true}
1419        ]});
1420        let expr = Expression::parse("items[*] | select(.active) | name | length()").unwrap();
1421        let result = execute(&val, &expr).unwrap();
1422        assert_eq!(result, vec![json!(2), json!(3)]);
1423    }
1424
1425    #[test]
1426    fn execute_pipeline_builtin_chain() {
1427        // keys() | length() — count number of keys
1428        let val = json!({"a": 1, "b": 2, "c": 3});
1429        let expr = Expression::parse("keys() | length()").unwrap();
1430        let result = execute(&val, &expr).unwrap();
1431        assert_eq!(result, vec![json!(3)]);
1432    }
1433
1434    #[test]
1435    fn execute_pipeline_values_then_length() {
1436        let val = json!({"a": 1, "b": 2});
1437        let expr = Expression::parse("values() | length()").unwrap();
1438        let result = execute(&val, &expr).unwrap();
1439        assert_eq!(result, vec![json!(2)]);
1440    }
1441
1442    #[test]
1443    fn execute_pipeline_path_builtin_select_path() {
1444        let val = json!({
1445            "data": {
1446                "users": [
1447                    {"name": "Alice", "age": 25},
1448                    {"name": "Bob", "age": 17}
1449                ]
1450            }
1451        });
1452        let expr = Expression::parse("data.users[*] | select(.age >= 18) | name").unwrap();
1453        let result = execute(&val, &expr).unwrap();
1454        assert_eq!(result, vec![json!("Alice")]);
1455    }
1456
1457    // ── Select with complex filters ──
1458
1459    #[test]
1460    fn execute_pipeline_select_lt() {
1461        let val = json!([1, 5, 10, 15, 20]);
1462        let expr = Expression::parse("[*] | select(. < 10)").unwrap();
1463        let result = execute(&val, &expr).unwrap();
1464        assert_eq!(result, vec![json!(1), json!(5)]);
1465    }
1466
1467    #[test]
1468    fn execute_pipeline_select_gte() {
1469        let val = json!([1, 5, 10, 15, 20]);
1470        let expr = Expression::parse("[*] | select(. >= 10)").unwrap();
1471        let result = execute(&val, &expr).unwrap();
1472        assert_eq!(result, vec![json!(10), json!(15), json!(20)]);
1473    }
1474
1475    #[test]
1476    fn execute_pipeline_select_eq_bool() {
1477        let val = json!({"items": [
1478            {"name": "a", "done": true},
1479            {"name": "b", "done": false},
1480            {"name": "c", "done": true}
1481        ]});
1482        let expr = Expression::parse("items[*] | select(.done == true) | name").unwrap();
1483        let result = execute(&val, &expr).unwrap();
1484        assert_eq!(result, vec![json!("a"), json!("c")]);
1485    }
1486
1487    #[test]
1488    fn execute_pipeline_select_eq_null() {
1489        let val = json!({"items": [
1490            {"name": "a", "email": null},
1491            {"name": "b", "email": "b@x.com"},
1492            {"name": "c", "email": null}
1493        ]});
1494        let expr = Expression::parse("items[*] | select(.email == null) | name").unwrap();
1495        let result = execute(&val, &expr).unwrap();
1496        assert_eq!(result, vec![json!("a"), json!("c")]);
1497    }
1498
1499    #[test]
1500    fn execute_pipeline_select_all_filtered_out() {
1501        let val = json!([1, 2, 3]);
1502        let expr = Expression::parse("[*] | select(. > 100)").unwrap();
1503        let result = execute(&val, &expr).unwrap();
1504        assert!(result.is_empty());
1505    }
1506
1507    #[test]
1508    fn execute_pipeline_select_on_empty_array() {
1509        let val = json!({"items": []});
1510        let expr = Expression::parse("items[*] | select(. > 0)").unwrap();
1511        let result = execute(&val, &expr).unwrap();
1512        assert!(result.is_empty());
1513    }
1514
1515    #[test]
1516    fn execute_pipeline_select_complex_and_or() {
1517        let val = json!({"items": [
1518            {"a": 1, "b": 2, "c": 3},
1519            {"a": 1, "b": 2, "c": 0},
1520            {"a": 0, "b": 0, "c": 0}
1521        ]});
1522        // a == 1 or (b == 2 and c == 3) — precedence: and before or
1523        let expr = Expression::parse("items[*] | select(.a == 1 or .b == 2 and .c == 3)").unwrap();
1524        let result = execute(&val, &expr).unwrap();
1525        // First: a==1 → true; Second: a==1 → true; Third: a==0 or (b==0 and c==0) → false
1526        assert_eq!(result.len(), 2);
1527    }
1528
1529    #[test]
1530    fn execute_pipeline_select_not_with_comparison() {
1531        let val = json!([
1532            {"status": "active"},
1533            {"status": "deleted"},
1534            {"status": "active"}
1535        ]);
1536        let expr = Expression::parse("[*] | select(not .status == \"deleted\")").unwrap();
1537        let result = execute(&val, &expr).unwrap();
1538        assert_eq!(result.len(), 2);
1539    }
1540
1541    #[test]
1542    fn execute_pipeline_select_string_comparison() {
1543        let val = json!(["apple", "banana", "cherry", "date"]);
1544        let expr = Expression::parse("[*] | select(. > \"c\")").unwrap();
1545        let result = execute(&val, &expr).unwrap();
1546        assert_eq!(result, vec![json!("cherry"), json!("date")]);
1547    }
1548
1549    #[test]
1550    fn execute_pipeline_select_regex_case_insensitive() {
1551        let val = json!(["Hello", "hello", "HELLO", "world"]);
1552        let expr = Expression::parse("[*] | select(. ~ \"(?i)^hello$\")").unwrap();
1553        let result = execute(&val, &expr).unwrap();
1554        assert_eq!(result, vec![json!("Hello"), json!("hello"), json!("HELLO")]);
1555    }
1556
1557    #[test]
1558    fn execute_pipeline_select_regex_digits() {
1559        let val = json!(["abc", "abc123", "456", "def"]);
1560        let expr = Expression::parse("[*] | select(. ~ \"\\\\d+\")").unwrap();
1561        let result = execute(&val, &expr).unwrap();
1562        assert_eq!(result, vec![json!("abc123"), json!("456")]);
1563    }
1564
1565    // ── set/del in pipelines ──
1566
1567    #[test]
1568    fn execute_set_then_del() {
1569        let val = json!({"a": 1, "b": 2});
1570        let expr = Expression::parse("set(.c, 3) | del(.a)").unwrap();
1571        let result = execute(&val, &expr).unwrap();
1572        assert_eq!(result[0]["b"], json!(2));
1573        assert_eq!(result[0]["c"], json!(3));
1574        assert!(result[0].get("a").is_none());
1575    }
1576
1577    #[test]
1578    fn execute_del_then_set() {
1579        let val = json!({"a": 1, "b": 2});
1580        let expr = Expression::parse("del(.b) | set(.c, 3)").unwrap();
1581        let result = execute(&val, &expr).unwrap();
1582        assert_eq!(result[0]["a"], json!(1));
1583        assert_eq!(result[0]["c"], json!(3));
1584        assert!(result[0].get("b").is_none());
1585    }
1586
1587    #[test]
1588    fn execute_multiple_set() {
1589        let val = json!({"x": 0, "y": 0});
1590        let expr = Expression::parse("set(.x, 1) | set(.y, 2)").unwrap();
1591        let result = execute(&val, &expr).unwrap();
1592        assert_eq!(result[0]["x"], json!(1));
1593        assert_eq!(result[0]["y"], json!(2));
1594    }
1595
1596    #[test]
1597    fn execute_multiple_del() {
1598        let val = json!({"a": 1, "b": 2, "c": 3});
1599        let expr = Expression::parse("del(.a) | del(.b)").unwrap();
1600        let result = execute(&val, &expr).unwrap();
1601        assert_eq!(result[0], json!({"c": 3}));
1602    }
1603
1604    #[test]
1605    fn execute_set_then_length() {
1606        let val = json!({"items": [1, 2]});
1607        let expr = Expression::parse("set(.name, \"test\") | keys() | length()").unwrap();
1608        let result = execute(&val, &expr).unwrap();
1609        // Original has 1 key "items", set adds "name" → 2 keys
1610        assert_eq!(result, vec![json!(2)]);
1611    }
1612
1613    #[test]
1614    fn execute_del_array_then_length() {
1615        let val = json!({"items": [1, 2, 3]});
1616        let expr = Expression::parse("del(.items[0]) | items | length()").unwrap();
1617        let result = execute(&val, &expr).unwrap();
1618        assert_eq!(result, vec![json!(2)]);
1619    }
1620
1621    // ── Slice combined with pipeline ──
1622
1623    #[test]
1624    fn execute_pipeline_slice_then_select() {
1625        let val = json!({"items": [
1626            {"name": "a", "price": 10},
1627            {"name": "b", "price": 200},
1628            {"name": "c", "price": 50},
1629            {"name": "d", "price": 300}
1630        ]});
1631        let expr = Expression::parse("items[1:3] | select(.price > 100) | name").unwrap();
1632        let result = execute(&val, &expr).unwrap();
1633        assert_eq!(result, vec![json!("b")]);
1634    }
1635
1636    #[test]
1637    fn execute_pipeline_slice_then_builtin() {
1638        // Slice [0:2] produces sub-arrays when used on nested data
1639        let val = json!({"items": [["a", "b"], ["c", "d", "e"]]});
1640        let expr = Expression::parse("items[0:2] | length()").unwrap();
1641        let result = execute(&val, &expr).unwrap();
1642        assert_eq!(result, vec![json!(2), json!(3)]);
1643    }
1644
1645    // ── Complex cross-phase ──
1646
1647    #[test]
1648    fn execute_cross_phase_slice_select_set() {
1649        let val = json!({"items": [
1650            {"name": "a", "active": true},
1651            {"name": "b", "active": false},
1652            {"name": "c", "active": true}
1653        ]});
1654        let expr = Expression::parse("items[0:2] | select(.active) | set(.selected, true)").unwrap();
1655        let result = execute(&val, &expr).unwrap();
1656        assert_eq!(result.len(), 1);
1657        assert_eq!(result[0]["name"], json!("a"));
1658        assert_eq!(result[0]["selected"], json!(true));
1659    }
1660
1661    // ── Edge: value_type_name ──
1662
1663    #[test]
1664    fn value_type_names() {
1665        assert_eq!(value_type_name(&json!(null)), "null");
1666        assert_eq!(value_type_name(&json!(true)), "boolean");
1667        assert_eq!(value_type_name(&json!(42)), "number");
1668        assert_eq!(value_type_name(&json!("hi")), "string");
1669        assert_eq!(value_type_name(&json!([])), "array");
1670        assert_eq!(value_type_name(&json!({})), "object");
1671    }
1672
1673    // ── Wildcard edge cases ──
1674
1675    #[test]
1676    fn extract_wildcard_nested_mixed_types() {
1677        let val = json!([{"name": "a"}, {"name": "b"}, {"name": "c"}]);
1678        let sel = Selector::parse("[*].name").unwrap();
1679        let result = extract(&val, &sel).unwrap();
1680        assert_eq!(result, vec![json!("a"), json!("b"), json!("c")]);
1681    }
1682
1683    #[test]
1684    fn extract_wildcard_single_element() {
1685        let val = json!([42]);
1686        let sel = Selector::parse("[*]").unwrap();
1687        let result = extract(&val, &sel).unwrap();
1688        assert_eq!(result, vec![json!(42)]);
1689    }
1690
1691    // ── Negative index edge cases ──
1692
1693    #[test]
1694    fn extract_negative_index_minus_2() {
1695        let val = json!([10, 20, 30, 40]);
1696        let sel = Selector::parse("[-2]").unwrap();
1697        let result = extract(&val, &sel).unwrap();
1698        assert_eq!(result, vec![json!(30)]);
1699    }
1700
1701    #[test]
1702    fn extract_negative_index_exactly_length() {
1703        // [-4] on 4-element array → index 0
1704        let val = json!([10, 20, 30, 40]);
1705        let sel = Selector::parse("[-4]").unwrap();
1706        let result = extract(&val, &sel).unwrap();
1707        assert_eq!(result, vec![json!(10)]);
1708    }
1709
1710    // ── Quoted key edge cases ──
1711
1712    #[test]
1713    fn extract_quoted_key_with_spaces() {
1714        let val = json!({"my key": "value"});
1715        let sel = Selector::parse("\"my key\"").unwrap();
1716        let result = extract(&val, &sel).unwrap();
1717        assert_eq!(result, vec![json!("value")]);
1718    }
1719
1720    #[test]
1721    fn extract_quoted_key_empty() {
1722        let val = json!({"": "empty key"});
1723        let sel = Selector::parse("\"\"").unwrap();
1724        let result = extract(&val, &sel).unwrap();
1725        assert_eq!(result, vec![json!("empty key")]);
1726    }
1727}