jsonpath_rust/query/
comparable.rs

1use 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}