jsonpath_rust/query/
segment.rs1use crate::parser::model::{Segment, Selector};
2use crate::query::queryable::Queryable;
3use crate::query::state::{Data, Pointer, State};
4use crate::query::Query;
5
6impl Query for Segment {
7 fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
8 match self {
9 Segment::Descendant(segment) => segment.process(step.flat_map(process_descendant)),
10 Segment::Selector(selector) => selector.process(step),
11 Segment::Selectors(selectors) => process_selectors(step, selectors),
12 }
13 }
14}
15
16fn process_selectors<'a, T: Queryable>(
17 step: State<'a, T>,
18 selectors: &Vec<Selector>,
19) -> State<'a, T> {
20 selectors
21 .into_iter()
22 .map(|s| s.process(step.clone()))
23 .reduce(State::reduce)
24 .unwrap_or(step.root.into())
25}
26
27fn process_descendant<T: Queryable>(data: Pointer<T>) -> Data<T> {
28 if let Some(array) = data.inner.as_array() {
29 Data::Ref(data.clone()).reduce(
30 Data::new_refs(
31 array
32 .iter()
33 .enumerate()
34 .map(|(i, elem)| Pointer::idx(elem, data.path.clone(), i))
35 .collect(),
36 )
37 .flat_map(process_descendant),
38 )
39 } else if let Some(object) = data.inner.as_object() {
40 Data::Ref(data.clone()).reduce(
41 Data::new_refs(
42 object
43 .into_iter()
44 .map(|(key, value)| Pointer::key(value, data.path.clone(), key))
45 .collect(),
46 )
47 .flat_map(process_descendant),
48 )
49 } else {
50 Data::Nothing
51 }
52}
53
54#[cfg(test)]
55mod tests {
56 use crate::parser::model::{Segment, Selector};
57 use crate::query::state::{Pointer, State};
58 use crate::query::Query;
59 use serde_json::json;
60
61 #[test]
62 fn test_process_selectors() {
63 let value = json!({"firstName": "John", "lastName" : "doe",});
64 let segment = Segment::Selectors(vec![
65 Selector::Name("firstName".to_string()),
66 Selector::Name("lastName".to_string()),
67 ]);
68 let step = segment.process(State::root(&value));
69
70 assert_eq!(
71 step.ok_ref(),
72 Some(vec![
73 Pointer::new(&json!("John"), "$['firstName']".to_string()),
74 Pointer::new(&json!("doe"), "$['lastName']".to_string())
75 ])
76 );
77 }
78
79 #[test]
80 fn test_process_descendant() {
81 let value = json!([{"name": "John"}, {"name": "doe"}]);
82 let segment = Segment::Descendant(Box::new(Segment::Selector(Selector::Wildcard)));
83 let step = segment.process(State::root(&value));
84
85 assert_eq!(
86 step.ok_ref(),
87 Some(vec![
88 Pointer::new(&json!({"name": "John"}), "$[0]".to_string()),
89 Pointer::new(&json!({"name": "doe"}), "$[1]".to_string()),
90 Pointer::new(&json!("John"), "$[0]['name']".to_string()),
91 Pointer::new(&json!("doe"), "$[1]['name']".to_string()),
92 ])
93 );
94 }
95
96 #[test]
97 fn test_process_descendant2() {
98 let value = json!({"o": [0,1,[2,3]]});
99 let segment = Segment::Descendant(Box::new(Segment::Selector(Selector::Index(1))));
100 let step = segment.process(State::root(&value));
101
102 assert_eq!(
103 step.ok_ref(),
104 Some(vec![
105 Pointer::new(&json!(1), "$['o'][1]".to_string()),
106 Pointer::new(&json!(3), "$['o'][2][1]".to_string()),
107 ])
108 );
109 }
110}