1 | use crate::parser::model::{Comparable, Literal, SingularQuery, SingularQuerySegment};
|
2 | use crate::query::queryable::Queryable;
|
3 | use crate::query::selector::{process_index, process_key};
|
4 | use crate::query::state::{Data, State};
|
5 | use crate::query::Query;
|
6 |
|
7 | impl Query for Comparable {
|
8 | fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
|
9 | match self {
|
10 | Comparable::Literal(lit: &Literal) => lit.process(state:step),
|
11 | Comparable::Function(tf: &TestFunction) => tf.process(state:step),
|
12 | Comparable::SingularQuery(query: &SingularQuery) => query.process(state:step),
|
13 | }
|
14 | }
|
15 | }
|
16 |
|
17 | impl Query for Literal {
|
18 | fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
|
19 | let val: T = match self {
|
20 | Literal::Int(v: &i64) => (*v).into(),
|
21 | Literal::Float(v: &f64) => (*v).into(),
|
22 | Literal::String(v: &String) => v.as_str().into(),
|
23 | Literal::Bool(v: &bool) => (*v).into(),
|
24 | Literal::Null => T::null(),
|
25 | };
|
26 |
|
27 | State::data(state.root, Data::Value(val))
|
28 | }
|
29 | }
|
30 |
|
31 | impl Query for SingularQuery {
|
32 | fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
|
33 | match self {
|
34 | SingularQuery::Current(segments: &Vec) => segments.process(state:step),
|
35 | SingularQuery::Root(segments: &Vec) => segments.process(state:step.shift_to_root()),
|
36 | }
|
37 | }
|
38 | }
|
39 |
|
40 | impl Query for SingularQuerySegment {
|
41 | fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
|
42 | match self {
|
43 | SingularQuerySegment::Index(idx: &i64) => step.flat_map(|d: Pointer<'a, T>| process_index(d, idx)),
|
44 | SingularQuerySegment::Name(key: &String) => step.flat_map(|d: Pointer<'a, T>| process_key(d, key)),
|
45 | }
|
46 | }
|
47 | }
|
48 |
|
49 | impl Query for Vec<SingularQuerySegment> {
|
50 | fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
|
51 | self.iter()
|
52 | .fold(init:state, |next: State<'a, T>, segment: &SingularQuerySegment| segment.process(state:next))
|
53 | }
|
54 | }
|
55 |
|
56 | #[cfg (test)]
|
57 | mod tests {
|
58 | use crate::parser::model::{Comparable, Literal, SingularQuery, SingularQuerySegment};
|
59 | use crate::query::state::{Data, Pointer, State};
|
60 | use crate::query::Query;
|
61 | use serde_json::json;
|
62 |
|
63 | #[test ]
|
64 | fn singular_query() {
|
65 | let value = json!({
|
66 | "result" : [
|
67 | {
|
68 | "message" : "Hello, Emmy! Your order number is: #100" ,
|
69 | "phoneNumber" : "255-301-9429" ,
|
70 | "phoneVariation" : "+90 398 588 10 73" ,
|
71 | "status" : "active" ,
|
72 | "name" : {
|
73 | "first" : "Blaise" ,
|
74 | "middle" : "Kyle" ,
|
75 | "last" : "Fadel"
|
76 | }
|
77 | }
|
78 | ]
|
79 | });
|
80 |
|
81 | let query = SingularQuery::Current(vec![
|
82 | SingularQuerySegment::Name("result" .to_string()),
|
83 | SingularQuerySegment::Index(0),
|
84 | SingularQuerySegment::Name("name" .to_string()),
|
85 | SingularQuerySegment::Name("first" .to_string()),
|
86 | ]);
|
87 |
|
88 | let state = State::root(&value);
|
89 |
|
90 | let result = query.process(state);
|
91 | assert_eq!(
|
92 | result.ok_ref(),
|
93 | Some(vec![Pointer::new(
|
94 | &json!("Blaise" ),
|
95 | "$['result'][0]['name']['first']" .to_string()
|
96 | )])
|
97 | );
|
98 | }
|
99 |
|
100 | #[test ]
|
101 | fn singular_query_root() {
|
102 | let value = json!({
|
103 | "result" : [
|
104 | {
|
105 | "message" : "Hello, Emmy! Your order number is: #100" ,
|
106 | "phoneNumber" : "255-301-9429" ,
|
107 | "phoneVariation" : "+90 398 588 10 73" ,
|
108 | "status" : "active" ,
|
109 | "name" : {
|
110 | "first" : "Blaise" ,
|
111 | "middle" : "Kyle" ,
|
112 | "last" : "Fadel"
|
113 | }
|
114 | }
|
115 | ]
|
116 | });
|
117 |
|
118 | let query = SingularQuery::Root(vec![
|
119 | SingularQuerySegment::Name("result" .to_string()),
|
120 | SingularQuerySegment::Index(0),
|
121 | SingularQuerySegment::Name("name" .to_string()),
|
122 | SingularQuerySegment::Name("first" .to_string()),
|
123 | ]);
|
124 |
|
125 | let state = State::data(
|
126 | &value,
|
127 | Data::new_ref(Pointer::new(&value, "$.name" .to_string())),
|
128 | );
|
129 |
|
130 | let result = query.process(state);
|
131 | assert_eq!(
|
132 | result.ok_ref(),
|
133 | Some(vec![Pointer::new(
|
134 | &json!("Blaise" ),
|
135 | "$['result'][0]['name']['first']" .to_string()
|
136 | )])
|
137 | );
|
138 | }
|
139 |
|
140 | #[test ]
|
141 | fn literal() {
|
142 | let value = json!({
|
143 | "result" : [
|
144 | {
|
145 | "message" : "Hello, Emmy! Your order number is: #100" ,
|
146 | "phoneNumber" : "255-301-9429" ,
|
147 | "phoneVariation" : "+90 398 588 10 73" ,
|
148 | "status" : "active" ,
|
149 | "name" : {
|
150 | "first" : "Blaise" ,
|
151 | "middle" : "Kyle" ,
|
152 | "last" : "Fadel"
|
153 | }
|
154 | }
|
155 | ]
|
156 | });
|
157 |
|
158 | let query = Comparable::Literal(Literal::String("Hello" .to_string()));
|
159 |
|
160 | let state = State::root(&value);
|
161 |
|
162 | let result = query.process(state);
|
163 | assert_eq!(result.ok_val(), Some(json!("Hello" )));
|
164 | }
|
165 | }
|
166 | |