1 | use crate::parser::model::Filter;
|
2 | use crate::query::queryable::Queryable;
|
3 | use crate::query::state::{Data, Pointer, State};
|
4 | use crate::query::Query;
|
5 |
|
6 | impl Query for Filter {
|
7 | fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
|
8 | let root = state.root;
|
9 | state.flat_map(|p| {
|
10 | if p.is_internal() {
|
11 | Data::Value(self.filter_item(p, root).into())
|
12 | } else if let Some(items) = p.inner.as_array() {
|
13 | Data::Refs(
|
14 | items
|
15 | .into_iter()
|
16 | .enumerate()
|
17 | .filter(|(_, item)| self.filter_item(Pointer::empty(*item), root))
|
18 | .map(|(idx, item)| Pointer::idx(item, p.path.clone(), idx))
|
19 | .collect(),
|
20 | )
|
21 | } else if let Some(items) = p.inner.as_object() {
|
22 | Data::Refs(
|
23 | items
|
24 | .into_iter()
|
25 | .filter(|(_, item)| self.filter_item(Pointer::empty(*item), root))
|
26 | .map(|(key, item)| Pointer::key(item, p.path.clone(), key))
|
27 | .collect(),
|
28 | )
|
29 | } else {
|
30 | return Data::Nothing;
|
31 | }
|
32 | })
|
33 | }
|
34 | }
|
35 |
|
36 | impl Filter {
|
37 | fn process_elem<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
|
38 | let process_cond: impl Fn(&Filter) -> bool = |filter: &Filter| {
|
39 | filterOption
|
40 | .process(state.clone())
|
41 | .ok_val()
|
42 | .and_then(|v: T| v.as_bool())
|
43 | .unwrap_or_default()
|
44 | };
|
45 | match self {
|
46 | Filter::Or(ors: &Vec) => State::bool(b:ors.iter().any(process_cond), state.root),
|
47 | Filter::And(ands: &Vec) => State::bool(b:ands.iter().all(process_cond), state.root),
|
48 | Filter::Atom(atom: &FilterAtom) => atom.process(state),
|
49 | }
|
50 | }
|
51 |
|
52 | fn filter_item<'a, T: Queryable>(&self, item: Pointer<'a, T>, root: &T) -> bool {
|
53 | self.process_elem(State::data(root, Data::Ref(item.clone())))
|
54 | .ok_val()
|
55 | .and_then(|v: T| v.as_bool())
|
56 | .unwrap_or_default()
|
57 | }
|
58 | }
|
59 |
|
60 | #[cfg (test)]
|
61 | mod tests {
|
62 | use crate::query::js_path;
|
63 | use serde_json::json;
|
64 |
|
65 | #[test ]
|
66 | fn smoke_ok() {
|
67 | let json = json!({"a" : [1,2,3]});
|
68 |
|
69 | assert_eq!(
|
70 | js_path("$.a[? @ > 1]" , &json),
|
71 | Ok(vec![
|
72 | (&json!(2), "$['a'][1]" .to_string()).into(),
|
73 | (&json!(3), "$['a'][2]" .to_string()).into(),
|
74 | ])
|
75 | );
|
76 | }
|
77 |
|
78 | #[test ]
|
79 | fn existence() {
|
80 | let json = json!({
|
81 | "a" : {
|
82 | "a" :{"b" :1},
|
83 | "c" : {
|
84 | "b" : 2
|
85 | },
|
86 | "d" : {
|
87 | "b1" : 3
|
88 | }
|
89 | }
|
90 | });
|
91 | assert_eq!(
|
92 | js_path("$.a[?@.b]" , &json),
|
93 | Ok(vec![
|
94 | (&json!({"b" :1}), "$['a']['a']" .to_string()).into(),
|
95 | (&json!({"b" :2}), "$['a']['c']" .to_string()).into(),
|
96 | ])
|
97 | );
|
98 | }
|
99 |
|
100 | #[test ]
|
101 | fn existence_or() {
|
102 | let json = json!({
|
103 | "a" : {
|
104 | "a" :{"b" :1},
|
105 | "c" : {
|
106 | "b" : 2
|
107 | },
|
108 | "d" : {
|
109 | "b1" : 3
|
110 | },
|
111 | "e" : {
|
112 | "b2" : 3
|
113 | }
|
114 | }
|
115 | });
|
116 | assert_eq!(
|
117 | js_path("$.a[?@.b || @.b1]" , &json),
|
118 | Ok(vec![
|
119 | (&json!({"b" :1}), "$['a']['a']" .to_string()).into(),
|
120 | (&json!({"b" :2}), "$['a']['c']" .to_string()).into(),
|
121 | (&json!({"b1" :3}), "$['a']['d']" .to_string()).into(),
|
122 | ])
|
123 | );
|
124 | }
|
125 | }
|
126 | |