Skip to main content

pick/selector/
extract.rs

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