jsonpath_rust/query/
comparable.rs1use crate::parser::model::{Comparable, Literal, SingularQuery, SingularQuerySegment};
2use crate::query::queryable::Queryable;
3use crate::query::selector::{process_index, process_key};
4use crate::query::state::{Data, State};
5use crate::query::Query;
6
7impl Query for Comparable {
8 fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
9 match self {
10 Comparable::Literal(lit) => lit.process(step),
11 Comparable::Function(tf) => tf.process(step),
12 Comparable::SingularQuery(query) => query.process(step),
13 }
14 }
15}
16
17impl Query for Literal {
18 fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
19 let val = match self {
20 Literal::Int(v) => (*v).into(),
21 Literal::Float(v) => (*v).into(),
22 Literal::String(v) => v.as_str().into(),
23 Literal::Bool(v) => (*v).into(),
24 Literal::Null => T::null(),
25 };
26
27 State::data(state.root, Data::Value(val))
28 }
29}
30
31impl Query for SingularQuery {
32 fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
33 match self {
34 SingularQuery::Current(segments) => segments.process(step),
35 SingularQuery::Root(segments) => segments.process(step.shift_to_root()),
36 }
37 }
38}
39
40impl Query for SingularQuerySegment {
41 fn process<'a, T: Queryable>(&self, step: State<'a, T>) -> State<'a, T> {
42 match self {
43 SingularQuerySegment::Index(idx) => step.flat_map(|d| process_index(d, idx)),
44 SingularQuerySegment::Name(key) => step.flat_map(|d| process_key(d, key)),
45 }
46 }
47}
48
49impl Query for Vec<SingularQuerySegment> {
50 fn process<'a, T: Queryable>(&self, state: State<'a, T>) -> State<'a, T> {
51 self.iter()
52 .fold(state, |next, segment| segment.process(next))
53 }
54}
55
56#[cfg(test)]
57mod 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}