1 | use crate::parser::model::{Segment, Selector};
|
2 | use crate::query::queryable::Queryable;
|
3 | use crate::query::state::{Data, Pointer, State};
|
4 | use crate::query::Query;
|
5 |
|
6 | impl Query for Segment {
|
7 | fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
|
8 | match self {
|
9 | Segment::Descendant(segment: &Box) => segment.process(state:step.flat_map(process_descendant)),
|
10 | Segment::Selector(selector: &Selector) => selector.process(state:step),
|
11 | Segment::Selectors(selectors: &Vec) => process_selectors(step, selectors),
|
12 | }
|
13 | }
|
14 | }
|
15 |
|
16 | fn 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(default:step.root.into())
|
25 | }
|
26 |
|
27 | fn 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)]
|
55 | mod 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 | }
|
111 | |