jsonpath_rust/query/
atom.rs1use crate::parser::model::FilterAtom;
2use crate::query::queryable::Queryable;
3use crate::query::state::{Data, State};
4use crate::query::Query;
5
6impl Query for FilterAtom {
7 fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
8 match self {
9 FilterAtom::Filter { expr, not } => {
10 let bool_res = expr.process(state);
11 if *not {
12 invert_bool(bool_res)
13 } else {
14 bool_res
15 }
16 }
17 FilterAtom::Test { expr, not } => {
18 let new_state = |b| State::bool(b, state.root);
19 let res = expr.process(state.clone());
20 if expr.is_res_bool() {
21 if *not {
22 invert_bool(res)
23 } else {
24 res
25 }
26 } else {
27 let struct_presented = match res.data {
31 Data::Ref(_) => true,
32 Data::Refs(elems) => !elems.is_empty(),
33 _ => false,
34 };
35
36 if struct_presented {
37 new_state(!*not)
38 } else {
39 new_state(*not)
40 }
41 }
42 }
43 FilterAtom::Comparison(cmp) => cmp.process(state),
44 }
45 }
46}
47
48fn invert_bool<T: Queryable>(state: State<T>) -> State<T> {
49 let root = state.root;
50 State::bool(
51 !state.ok_val().and_then(|v| v.as_bool()).unwrap_or_default(),
52 root,
53 )
54}
55
56#[cfg(test)]
57mod tests {
58 use crate::parser::model::Comparable;
59 use crate::parser::model::Literal;
60 use crate::parser::model::SingularQuery;
61 use crate::parser::model::SingularQuerySegment;
62 use crate::parser::model::{Comparison, FilterAtom};
63 use crate::q_segment;
64 use crate::query::queryable::Queryable;
65 use crate::query::state::State;
66 use crate::query::Query;
67 use crate::{atom, comparable, lit};
68 use crate::{cmp, singular_query};
69 use crate::{filter_, q_segments};
70 use serde_json::json;
71
72 #[test]
73 fn test_comparison() {
74 let json = json!({"i": 1});
75 let atom = atom!(comparable!(lit!(i 1)), ">=", comparable!(lit!(i 1)));
76 let state = State::root(&json);
77 let res = atom.process(state);
78 assert_eq!(res.ok_val().and_then(|v| v.as_bool()), Some(true));
79 }
80
81 #[test]
82 fn test_not_filter_atom() {
83 let json = json!({"a": 1 , "b": 2});
84 let state = State::root(&json);
85
86 let f1 = filter_!(atom!(
87 comparable!(> SingularQuery::Current(vec![])),
88 ">",
89 comparable!(lit!(i 2))
90 ));
91 let f2 = filter_!(atom!(
92 comparable!(> singular_query!(b)),
93 "!=",
94 comparable!(> singular_query!(a))
95 ));
96
97 let atom_or = atom!(!filter_!(or f1.clone(), f2.clone()));
98 let atom_and = atom!(!filter_!(and f1, f2));
99
100 assert_eq!(
101 atom_or
102 .process(state.clone())
103 .ok_val()
104 .and_then(|v| v.as_bool()),
105 Some(true)
106 );
107 assert_eq!(
108 atom_and.process(state).ok_val().and_then(|v| v.as_bool()),
109 Some(true)
110 );
111 }
112}