jsonpath_rust/path/
index.rs

1use std::fmt::Debug;
2
3use crate::jsp_idx;
4use crate::parser::model::{FilterExpression, FilterSign, JsonPath};
5
6use crate::path::top::ObjectField;
7use crate::path::{json_path_instance, process_operand, JsonPathValue, Path, PathInstance};
8use crate::JsonPathValue::{NoValue, Slice};
9
10use super::{JsonLike, TopPaths};
11
12/// process the slice like [start:end:step]
13#[derive(Debug)]
14pub struct ArraySlice<T> {
15    start_index: i32,
16    end_index: i32,
17    step: usize,
18    _t: std::marker::PhantomData<T>,
19}
20
21impl<T> ArraySlice<T> {
22    pub(crate) fn new(start_index: i32, end_index: i32, step: usize) -> Self {
23        ArraySlice {
24            start_index,
25            end_index,
26            step,
27            _t: std::marker::PhantomData,
28        }
29    }
30
31    fn end(&self, len: i32) -> Option<usize> {
32        if self.end_index >= 0 {
33            if self.end_index > len {
34                None
35            } else {
36                Some(self.end_index as usize)
37            }
38        } else if self.end_index < -len {
39            None
40        } else {
41            Some((len - (-self.end_index)) as usize)
42        }
43    }
44
45    fn start(&self, len: i32) -> Option<usize> {
46        if self.start_index >= 0 {
47            if self.start_index > len {
48                None
49            } else {
50                Some(self.start_index as usize)
51            }
52        } else if self.start_index < -len {
53            None
54        } else {
55            Some((len - -self.start_index) as usize)
56        }
57    }
58
59    fn process<'a, F>(&self, elements: &'a [F]) -> Vec<(&'a F, usize)> {
60        let len = elements.len() as i32;
61        let mut filtered_elems: Vec<(&'a F, usize)> = vec![];
62        match (self.start(len), self.end(len)) {
63            (Some(start_idx), Some(end_idx)) => {
64                let end_idx = if end_idx == 0 {
65                    elements.len()
66                } else {
67                    end_idx
68                };
69                for idx in (start_idx..end_idx).step_by(self.step) {
70                    if let Some(v) = elements.get(idx) {
71                        filtered_elems.push((v, idx))
72                    }
73                }
74                filtered_elems
75            }
76            _ => filtered_elems,
77        }
78    }
79}
80
81impl<'a, T> Path<'a> for ArraySlice<T>
82where
83    T: JsonLike,
84{
85    type Data = T;
86
87    fn find(&self, input: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
88        input.flat_map_slice(|data, pref| {
89            data.as_array()
90                .map(|elems| self.process(elems))
91                .and_then(|v| {
92                    if v.is_empty() {
93                        None
94                    } else {
95                        let v = v.into_iter().map(|(e, i)| (e, jsp_idx(&pref, i))).collect();
96                        Some(JsonPathValue::map_vec(v))
97                    }
98                })
99                .unwrap_or_else(|| vec![NoValue])
100        })
101    }
102}
103
104/// process the simple index like [index]
105pub struct ArrayIndex<T> {
106    index: usize,
107    _t: std::marker::PhantomData<T>,
108}
109
110impl<T> ArrayIndex<T> {
111    pub(crate) fn new(index: usize) -> Self {
112        ArrayIndex {
113            index,
114            _t: std::marker::PhantomData,
115        }
116    }
117}
118
119impl<'a, T> Path<'a> for ArrayIndex<T>
120where
121    T: JsonLike,
122{
123    type Data = T;
124
125    fn find(&self, input: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
126        input.flat_map_slice(|data, pref| {
127            data.as_array()
128                .and_then(|elems| elems.get(self.index))
129                .map(|e| vec![JsonPathValue::new_slice(e, jsp_idx(&pref, self.index))])
130                .unwrap_or_else(|| vec![NoValue])
131        })
132    }
133}
134
135/// process @ element
136pub struct Current<'a, T> {
137    tail: Option<PathInstance<'a, T>>,
138    _t: std::marker::PhantomData<T>,
139}
140
141impl<'a, T> Current<'a, T>
142where
143    T: JsonLike,
144{
145    pub(crate) fn from(jp: &'a JsonPath<T>, root: &'a T) -> Self {
146        match jp {
147            JsonPath::Empty => Current::none(),
148            tail => Current::new(Box::new(json_path_instance(tail, root))),
149        }
150    }
151    pub(crate) fn new(tail: PathInstance<'a, T>) -> Self {
152        Current {
153            tail: Some(tail),
154            _t: std::marker::PhantomData,
155        }
156    }
157    pub(crate) fn none() -> Self {
158        Current {
159            tail: None,
160            _t: std::marker::PhantomData,
161        }
162    }
163}
164
165impl<'a, T> Path<'a> for Current<'a, T>
166where
167    T: JsonLike,
168{
169    type Data = T;
170
171    fn find(&self, input: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
172        self.tail
173            .as_ref()
174            .map(|p| p.find(input.clone()))
175            .unwrap_or_else(|| vec![input])
176    }
177}
178
179/// the list of indexes like [1,2,3]
180pub struct UnionIndex<'a, T> {
181    indexes: Vec<TopPaths<'a, T>>,
182}
183
184impl<'a, T> UnionIndex<'a, T>
185where
186    T: JsonLike,
187{
188    pub fn from_indexes(elems: &'a [T]) -> Self {
189        let mut indexes: Vec<TopPaths<'a, T>> = vec![];
190
191        for idx in elems.iter() {
192            indexes.push(TopPaths::ArrayIndex(ArrayIndex::new(
193                idx.as_u64().unwrap() as usize
194            )))
195        }
196
197        UnionIndex::new(indexes)
198    }
199    pub fn from_keys(elems: &'a [String]) -> Self {
200        let mut indexes: Vec<TopPaths<'a, T>> = vec![];
201
202        for key in elems.iter() {
203            indexes.push(TopPaths::ObjectField(ObjectField::new(key)))
204        }
205
206        UnionIndex::new(indexes)
207    }
208
209    pub fn new(indexes: Vec<TopPaths<'a, T>>) -> Self {
210        UnionIndex { indexes }
211    }
212}
213
214impl<'a, T> Path<'a> for UnionIndex<'a, T>
215where
216    T: JsonLike,
217{
218    type Data = T;
219
220    fn find(&self, input: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
221        self.indexes
222            .iter()
223            .flat_map(|e| e.find(input.clone()))
224            .collect()
225    }
226}
227
228/// process filter element like [?(op sign op)]
229pub enum FilterPath<'a, T> {
230    Filter {
231        left: PathInstance<'a, T>,
232        right: PathInstance<'a, T>,
233        op: &'a FilterSign,
234    },
235    Or {
236        left: PathInstance<'a, T>,
237        right: PathInstance<'a, T>,
238    },
239    And {
240        left: PathInstance<'a, T>,
241        right: PathInstance<'a, T>,
242    },
243    Not {
244        exp: PathInstance<'a, T>,
245    },
246}
247
248impl<'a, T> FilterPath<'a, T>
249where
250    T: JsonLike,
251{
252    pub(crate) fn new(expr: &'a FilterExpression<T>, root: &'a T) -> Self {
253        match expr {
254            FilterExpression::Atom(left, op, right) => FilterPath::Filter {
255                left: process_operand(left, root),
256                right: process_operand(right, root),
257                op,
258            },
259            FilterExpression::And(l, r) => FilterPath::And {
260                left: Box::new(FilterPath::new(l, root)),
261                right: Box::new(FilterPath::new(r, root)),
262            },
263            FilterExpression::Or(l, r) => FilterPath::Or {
264                left: Box::new(FilterPath::new(l, root)),
265                right: Box::new(FilterPath::new(r, root)),
266            },
267            FilterExpression::Not(exp) => FilterPath::Not {
268                exp: Box::new(FilterPath::new(exp, root)),
269            },
270        }
271    }
272    fn compound(
273        one: &'a FilterSign,
274        two: &'a FilterSign,
275        left: Vec<JsonPathValue<T>>,
276        right: Vec<JsonPathValue<T>>,
277    ) -> bool {
278        FilterPath::process_atom(one, left.clone(), right.clone())
279            || FilterPath::process_atom(two, left, right)
280    }
281    fn process_atom(
282        op: &'a FilterSign,
283        left: Vec<JsonPathValue<T>>,
284        right: Vec<JsonPathValue<T>>,
285    ) -> bool {
286        match op {
287            FilterSign::Equal => <T as JsonLike>::eq(
288                JsonPathValue::vec_as_data(left),
289                JsonPathValue::vec_as_data(right),
290            ),
291            FilterSign::Unequal => !FilterPath::process_atom(&FilterSign::Equal, left, right),
292            FilterSign::Less => <T as JsonLike>::less(
293                JsonPathValue::vec_as_data(left),
294                JsonPathValue::vec_as_data(right),
295            ),
296            FilterSign::LeOrEq => {
297                FilterPath::compound(&FilterSign::Less, &FilterSign::Equal, left, right)
298            }
299            FilterSign::Greater => <T as JsonLike>::less(
300                JsonPathValue::vec_as_data(right),
301                JsonPathValue::vec_as_data(left),
302            ),
303            FilterSign::GrOrEq => {
304                FilterPath::compound(&FilterSign::Greater, &FilterSign::Equal, left, right)
305            }
306            FilterSign::Regex => <T as JsonLike>::regex(
307                JsonPathValue::vec_as_data(left),
308                JsonPathValue::vec_as_data(right),
309            ),
310            FilterSign::In => <T as JsonLike>::inside(
311                JsonPathValue::vec_as_data(left),
312                JsonPathValue::vec_as_data(right),
313            ),
314            FilterSign::Nin => !FilterPath::process_atom(&FilterSign::In, left, right),
315            FilterSign::NoneOf => !FilterPath::process_atom(&FilterSign::AnyOf, left, right),
316            FilterSign::AnyOf => <T as JsonLike>::any_of(
317                JsonPathValue::vec_as_data(left),
318                JsonPathValue::vec_as_data(right),
319            ),
320            FilterSign::SubSetOf => <T as JsonLike>::sub_set_of(
321                JsonPathValue::vec_as_data(left),
322                JsonPathValue::vec_as_data(right),
323            ),
324            FilterSign::Exists => !JsonPathValue::vec_as_data(left).is_empty(),
325            FilterSign::Size => <T as JsonLike>::size(
326                JsonPathValue::vec_as_data(left),
327                JsonPathValue::vec_as_data(right),
328            ),
329        }
330    }
331
332    fn process(&self, curr_el: &'a T) -> bool {
333        let pref = String::new();
334        match self {
335            FilterPath::Filter { left, right, op } => FilterPath::process_atom(
336                op,
337                left.find(Slice(curr_el, pref.clone())),
338                right.find(Slice(curr_el, pref)),
339            ),
340            FilterPath::Or { left, right } => {
341                if !JsonPathValue::vec_as_data(left.find(Slice(curr_el, pref.clone()))).is_empty() {
342                    true
343                } else {
344                    !JsonPathValue::vec_as_data(right.find(Slice(curr_el, pref))).is_empty()
345                }
346            }
347            FilterPath::And { left, right } => {
348                if JsonPathValue::vec_as_data(left.find(Slice(curr_el, pref.clone()))).is_empty() {
349                    false
350                } else {
351                    !JsonPathValue::vec_as_data(right.find(Slice(curr_el, pref))).is_empty()
352                }
353            }
354            FilterPath::Not { exp } => {
355                JsonPathValue::vec_as_data(exp.find(Slice(curr_el, pref))).is_empty()
356            }
357        }
358    }
359}
360
361impl<'a, T> Path<'a> for FilterPath<'a, T>
362where
363    T: JsonLike,
364{
365    type Data = T;
366
367    fn find(&self, input: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
368        input.flat_map_slice(|data, pref| {
369            let mut res = vec![];
370            if data.is_array() {
371                let elems = data.as_array().unwrap();
372                for (i, el) in elems.iter().enumerate() {
373                    if self.process(el) {
374                        res.push(Slice(el, jsp_idx(&pref, i)))
375                    }
376                }
377            } else if self.process(data) {
378                res.push(Slice(data, pref))
379            }
380
381            // match data {
382            //     Array(elems) => {
383            //         for (i, el) in elems.iter().enumerate() {
384            //             if self.process(el) {
385            //                 res.push(Slice(el, jsp_idx(&pref, i)))
386            //             }
387            //         }
388            //     }
389            //     el => {
390            //         if self.process(el) {
391            //             res.push(Slice(el, pref))
392            //         }
393            //     }
394            // }
395            if res.is_empty() {
396                vec![NoValue]
397            } else {
398                res
399            }
400        })
401    }
402}
403
404#[cfg(test)]
405mod tests {
406    use crate::jp_v;
407    use crate::parser::macros::{chain, filter, idx, op};
408    use crate::parser::model::{FilterExpression, FilterSign, JsonPath, JsonPathIndex, Operand};
409    use crate::path::index::{ArrayIndex, ArraySlice};
410    use crate::path::JsonPathValue;
411    use crate::path::{json_path_instance, Path};
412    use crate::JsonPathValue::NoValue;
413
414    use crate::path;
415    use serde_json::{json, Value};
416
417    #[test]
418    fn array_slice_end_start_test() {
419        let array = [0, 1, 2, 3, 4, 5];
420        let len = array.len() as i32;
421        let mut slice: ArraySlice<Value> = ArraySlice::new(0, 0, 0);
422
423        assert_eq!(slice.start(len).unwrap(), 0);
424        slice.start_index = 1;
425
426        assert_eq!(slice.start(len).unwrap(), 1);
427
428        slice.start_index = 2;
429        assert_eq!(slice.start(len).unwrap(), 2);
430
431        slice.start_index = 5;
432        assert_eq!(slice.start(len).unwrap(), 5);
433
434        slice.start_index = 7;
435        assert_eq!(slice.start(len), None);
436
437        slice.start_index = -1;
438        assert_eq!(slice.start(len).unwrap(), 5);
439
440        slice.start_index = -5;
441        assert_eq!(slice.start(len).unwrap(), 1);
442
443        slice.end_index = 0;
444        assert_eq!(slice.end(len).unwrap(), 0);
445
446        slice.end_index = 5;
447        assert_eq!(slice.end(len).unwrap(), 5);
448
449        slice.end_index = -1;
450        assert_eq!(slice.end(len).unwrap(), 5);
451
452        slice.end_index = -5;
453        assert_eq!(slice.end(len).unwrap(), 1);
454    }
455
456    #[test]
457    fn slice_test() {
458        let array = json!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
459
460        let mut slice = ArraySlice::new(0, 6, 2);
461        let j1 = json!(0);
462        let j2 = json!(2);
463        let j4 = json!(4);
464        assert_eq!(
465            slice.find(JsonPathValue::new_slice(&array, "a".to_string())),
466            jp_v![&j1;"a[0]", &j2;"a[2]", &j4;"a[4]"]
467        );
468
469        slice.step = 3;
470        let j0 = json!(0);
471        let j3 = json!(3);
472        assert_eq!(slice.find(jp_v!(&array)), jp_v![&j0;"[0]", &j3;"[3]"]);
473
474        slice.start_index = -1;
475        slice.end_index = 1;
476
477        assert_eq!(
478            slice.find(JsonPathValue::new_slice(&array, "a".to_string())),
479            vec![NoValue]
480        );
481
482        slice.start_index = -10;
483        slice.end_index = 10;
484
485        let j1 = json!(1);
486        let j4 = json!(4);
487        let j7 = json!(7);
488
489        assert_eq!(
490            slice.find(JsonPathValue::new_slice(&array, "a".to_string())),
491            jp_v![&j1;"a[1]", &j4;"a[4]", &j7;"a[7]"]
492        );
493    }
494
495    #[test]
496    fn index_test() {
497        let array = json!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
498
499        let mut index = ArrayIndex::new(0);
500        let j0 = json!(0);
501        let j10 = json!(10);
502        assert_eq!(
503            index.find(JsonPathValue::new_slice(&array, "a".to_string())),
504            jp_v![&j0;"a[0]",]
505        );
506        index.index = 10;
507        assert_eq!(
508            index.find(JsonPathValue::new_slice(&array, "a".to_string())),
509            jp_v![&j10;"a[10]",]
510        );
511        index.index = 100;
512        assert_eq!(
513            index.find(JsonPathValue::new_slice(&array, "a".to_string())),
514            vec![NoValue]
515        );
516    }
517
518    #[test]
519    fn current_test() {
520        let json = json!(
521        {
522            "object":{
523                "field_1":[1,2,3],
524                "field_2":42,
525                "field_3":{"a":"b"}
526
527            }
528        });
529
530        let chain = chain!(path!($), path!("object"), path!(@));
531
532        let path_inst = json_path_instance(&chain, &json);
533        let res = json!({
534            "field_1":[1,2,3],
535            "field_2":42,
536            "field_3":{"a":"b"}
537        });
538
539        let expected_res = jp_v!(&res;"$.['object']",);
540        assert_eq!(path_inst.find(jp_v!(&json)), expected_res);
541
542        let cur = path!(@,path!("field_3"),path!("a"));
543        let chain = chain!(path!($), path!("object"), cur);
544
545        let path_inst = json_path_instance(&chain, &json);
546        let res1 = json!("b");
547
548        let expected_res = vec![JsonPathValue::new_slice(
549            &res1,
550            "$.['object'].['field_3'].['a']".to_string(),
551        )];
552        assert_eq!(path_inst.find(jp_v!(&json)), expected_res);
553    }
554
555    #[test]
556    fn filter_exist_test() {
557        let json = json!({
558            "threshold" : 3,
559            "key":[{"field":[1,2,3,4,5],"field1":[7]},{"field":42}],
560        });
561
562        let index = path!(idx!(?filter!(op!(path!(@, path!("field"))), "exists", op!())));
563        let chain = chain!(path!($), path!("key"), index, path!("field"));
564
565        let path_inst = json_path_instance(&chain, &json);
566
567        let exp1 = json!([1, 2, 3, 4, 5]);
568        let exp2 = json!(42);
569        let expected_res = jp_v!(&exp1;"$.['key'][0].['field']",&exp2;"$.['key'][1].['field']");
570        assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
571    }
572
573    #[test]
574    fn filter_gr_test() {
575        let json = json!({
576            "threshold" : 4,
577            "key":[
578                {"field":1},
579                {"field":10},
580                {"field":4},
581                {"field":5},
582                {"field":1},
583            ]
584        });
585        let _exp1 = json!( {"field":10});
586        let _exp2 = json!( {"field":5});
587        let exp3 = json!( {"field":4});
588        let exp4 = json!( {"field":1});
589
590        let index = path!(
591            idx!(?filter!(op!(path!(@, path!("field"))), ">", op!(chain!(path!($), path!("threshold")))))
592        );
593
594        let chain = chain!(path!($), path!("key"), index);
595
596        let path_inst = json_path_instance(&chain, &json);
597
598        let exp1 = json!( {"field":10});
599        let exp2 = json!( {"field":5});
600        let expected_res = jp_v![&exp1;"$.['key'][1]", &exp2;"$.['key'][3]"];
601        assert_eq!(
602            path_inst.find(JsonPathValue::from_root(&json)),
603            expected_res
604        );
605        let expected_res = jp_v![&exp1;"$.['key'][1]", &exp2;"$.['key'][3]"];
606        assert_eq!(
607            path_inst.find(JsonPathValue::from_root(&json)),
608            expected_res
609        );
610
611        let index = path!(
612            idx!(?filter!(op!(path!(@, path!("field"))), ">=", op!(chain!(path!($), path!("threshold")))))
613        );
614        let chain = chain!(path!($), path!("key"), index);
615        let path_inst = json_path_instance(&chain, &json);
616        let expected_res = jp_v![
617            &exp1;"$.['key'][1]", &exp3;"$.['key'][2]", &exp2;"$.['key'][3]"];
618        assert_eq!(
619            path_inst.find(JsonPathValue::from_root(&json)),
620            expected_res
621        );
622
623        let index = path!(
624            idx!(?filter!(op!(path!(@, path!("field"))), "<", op!(chain!(path!($), path!("threshold")))))
625        );
626        let chain = chain!(path!($), path!("key"), index);
627        let path_inst = json_path_instance(&chain, &json);
628        let expected_res = jp_v![&exp4;"$.['key'][0]", &exp4;"$.['key'][4]"];
629        assert_eq!(
630            path_inst.find(JsonPathValue::from_root(&json)),
631            expected_res
632        );
633
634        let index = path!(
635            idx!(?filter!(op!(path!(@, path!("field"))), "<=", op!(chain!(path!($), path!("threshold")))))
636        );
637        let chain = chain!(path!($), path!("key"), index);
638        let path_inst = json_path_instance(&chain, &json);
639        let expected_res = jp_v![
640            &exp4;"$.['key'][0]",
641            &exp3;"$.['key'][2]",
642            &exp4;"$.['key'][4]"];
643        assert_eq!(
644            path_inst.find(JsonPathValue::from_root(&json)),
645            expected_res
646        );
647    }
648
649    #[test]
650    fn filter_regex_test() {
651        let json = json!({
652            "key":[
653                {"field":"a11#"},
654                {"field":"a1#1"},
655                {"field":"a#11"},
656                {"field":"#a11"},
657            ]
658        });
659
660        let index = idx!(?filter!(op!(path!(@,path!("field"))),"~=", op!("[a-zA-Z]+[0-9]#[0-9]+")));
661        let chain = chain!(path!($), path!("key"), path!(index));
662
663        let path_inst = json_path_instance(&chain, &json);
664
665        let exp2 = json!( {"field":"a1#1"});
666        let expected_res = jp_v![&exp2;"$.['key'][1]",];
667        assert_eq!(
668            path_inst.find(JsonPathValue::from_root(&json)),
669            expected_res
670        )
671    }
672
673    #[test]
674    fn filter_any_of_test() {
675        let json = json!({
676            "key":[
677                {"field":"a11#"},
678                {"field":"a1#1"},
679                {"field":"a#11"},
680                {"field":"#a11"},
681            ]
682        });
683
684        let index = idx!(?filter!(
685            op!(path!(@,path!("field"))),
686            "anyOf",
687            op!(s ["a11#","aaa","111"])
688        ));
689
690        let chain = chain!(path!($), JsonPath::Field(String::from("key")), path!(index));
691
692        let path_inst = json_path_instance(&chain, &json);
693
694        let exp2 = json!( {"field":"a11#"});
695        let expected_res = jp_v![&exp2;"$.['key'][0]",];
696        assert_eq!(
697            path_inst.find(JsonPathValue::from_root(&json)),
698            expected_res
699        )
700    }
701
702    #[test]
703    fn size_test() {
704        let json = json!({
705            "key":[
706                {"field":"aaaa"},
707                {"field":"bbb"},
708                {"field":"cc"},
709                {"field":"dddd"},
710                {"field":[1,1,1,1]},
711            ]
712        });
713
714        let index = idx!(?filter!(op!(path!(@, path!("field"))),"size",op!(4)));
715        let chain = chain!(path!($), path!("key"), path!(index));
716        let path_inst = json_path_instance(&chain, &json);
717
718        let f1 = json!( {"field":"aaaa"});
719        let f2 = json!( {"field":"dddd"});
720        let f3 = json!( {"field":[1,1,1,1]});
721
722        let expected_res = jp_v![&f1;"$.['key'][0]", &f2;"$.['key'][3]", &f3;"$.['key'][4]"];
723        assert_eq!(
724            path_inst.find(JsonPathValue::from_root(&json)),
725            expected_res
726        )
727    }
728
729    #[test]
730    fn nested_filter_test() {
731        let json = json!({
732            "obj":{
733                "id":1,
734                "not_id": 2,
735                "more_then_id" :3
736            }
737        });
738        let index = idx!(?filter!(
739            op!(path!(@,path!("not_id"))), "==",op!(2)
740        ));
741        let chain = chain!(path!($), path!("obj"), path!(index));
742        let path_inst = json_path_instance(&chain, &json);
743        let js = json!({
744            "id":1,
745            "not_id": 2,
746            "more_then_id" :3
747        });
748        assert_eq!(
749            path_inst.find(JsonPathValue::from_root(&json)),
750            jp_v![&js;"$.['obj']",]
751        )
752    }
753
754    #[test]
755    fn or_arr_test() {
756        let json = json!({
757            "key":[
758                {"city":"London","capital":true, "size": "big"},
759                {"city":"Berlin","capital":true,"size": "big"},
760                {"city":"Tokyo","capital":true,"size": "big"},
761                {"city":"Moscow","capital":true,"size": "big"},
762                {"city":"Athlon","capital":false,"size": "small"},
763                {"city":"Dortmund","capital":false,"size": "big"},
764                {"city":"Dublin","capital":true,"size": "small"},
765            ]
766        });
767        let index = idx!(?filter!(
768            filter!(op!(path!(@,path!("capital"))), "==", op!(false)),
769            ||,
770            filter!(op!(path!(@,path!("size"))), "==", op!("small"))
771        )
772        );
773        let chain = chain!(path!($), path!("key"), path!(index), path!("city"));
774        let path_inst = json_path_instance(&chain, &json);
775        let a = json!("Athlon");
776        let d = json!("Dortmund");
777        let dd = json!("Dublin");
778        assert_eq!(
779            path_inst.find(JsonPathValue::from_root(&json)),
780            jp_v![
781                &a;"$.['key'][4].['city']",
782                &d;"$.['key'][5].['city']",
783                &dd;"$.['key'][6].['city']"]
784        )
785    }
786
787    #[test]
788    fn or_obj_test() {
789        let json = json!({
790            "key":{
791             "id":1,
792             "name":"a",
793             "another":"b"
794            }
795        });
796        let index = idx!(?filter!(
797            filter!(op!(path!(@,path!("name"))), "==", op!("a")),
798            ||,
799            filter!(op!(path!(@,path!("another"))), "==", op!("b"))
800        )
801        );
802        let chain = chain!(path!($), path!("key"), path!(index), path!("id"));
803        let path_inst = json_path_instance(&chain, &json);
804        let j1 = json!(1);
805        assert_eq!(
806            path_inst.find(JsonPathValue::from_root(&json)),
807            jp_v![&j1;"$.['key'].['id']",]
808        )
809    }
810
811    #[test]
812    fn or_obj_2_test() {
813        let json = json!({
814            "key":{
815             "id":1,
816             "name":"a",
817             "another":"d"
818            }
819        });
820        let index = idx!(?filter!(
821            filter!(op!(path!(@,path!("name"))), "==", op!("c")),
822            ||,
823            filter!(op!(path!(@,path!("another"))), "==", op!("d"))
824        )
825        );
826        let chain = chain!(path!($), path!("key"), path!(index), path!("id"));
827        let path_inst = json_path_instance(&chain, &json);
828        let j1 = json!(1);
829        assert_eq!(
830            path_inst.find(JsonPathValue::from_root(&json)),
831            jp_v![&j1;"$.['key'].['id']",]
832        )
833    }
834
835    #[test]
836    fn and_arr_test() {
837        let json = json!({
838            "key":[
839                {"city":"London","capital":true, "size": "big"},
840                {"city":"Berlin","capital":true,"size": "big"},
841                {"city":"Tokyo","capital":true,"size": "big"},
842                {"city":"Moscow","capital":true,"size": "big"},
843                {"city":"Athlon","capital":false,"size": "small"},
844                {"city":"Dortmund","capital":false,"size": "big"},
845                {"city":"Dublin","capital":true,"size": "small"},
846            ]
847        });
848        let index = idx!(?filter!(
849            filter!(op!(path!(@,path!("capital"))), "==", op!(false)),
850            &&,
851            filter!(op!(path!(@,path!("size"))), "==", op!("small"))
852        )
853        );
854        let chain = chain!(path!($), path!("key"), path!(index), path!("city"));
855        let path_inst = json_path_instance(&chain, &json);
856        let a = json!("Athlon");
857        let value = jp_v!( &a;"$.['key'][4].['city']",);
858        assert_eq!(path_inst.find(JsonPathValue::from_root(&json)), value)
859    }
860
861    #[test]
862    fn and_obj_test() {
863        let json = json!({
864            "key":{
865             "id":1,
866             "name":"a",
867             "another":"b"
868            }
869        });
870        let index = idx!(?filter!(
871            filter!(op!(path!(@,path!("name"))), "==", op!("a")),
872            &&,
873            filter!(op!(path!(@,path!("another"))), "==", op!("b"))
874        )
875        );
876        let chain = chain!(path!($), path!("key"), path!(index), path!("id"));
877        let path_inst = json_path_instance(&chain, &json);
878        let j1 = json!(1);
879        assert_eq!(
880            path_inst.find(JsonPathValue::from_root(&json)),
881            jp_v![&j1; "$.['key'].['id']",]
882        )
883    }
884
885    #[test]
886    fn and_obj_2_test() {
887        let json = json!({
888            "key":{
889             "id":1,
890             "name":"a",
891             "another":"d"
892            }
893        });
894        let index = idx!(?filter!(
895            filter!(op!(path!(@,path!("name"))), "==", op!("c")),
896            &&,
897            filter!(op!(path!(@,path!("another"))), "==", op!("d"))
898        )
899        );
900        let chain = chain!(path!($), path!("key"), path!(index), path!("id"));
901        let path_inst = json_path_instance(&chain, &json);
902        assert_eq!(
903            path_inst.find(JsonPathValue::from_root(&json)),
904            vec![NoValue]
905        )
906    }
907}