1use crate::jsp_obj;
2use crate::parser::model::*;
3use crate::path::{json_path_instance, JsonPathValue, Path};
4use crate::JsonPathValue::{NewValue, NoValue, Slice};
5
6use super::{JsonLike, TopPaths};
7
8pub struct Wildcard<T> {
10 _t: std::marker::PhantomData<T>,
11}
12
13impl<T> Wildcard<T> {
14 pub fn new() -> Self {
15 Self {
16 _t: std::marker::PhantomData,
17 }
18 }
19}
20
21impl<T> Default for Wildcard<T> {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl<'a, T> Path<'a> for Wildcard<T>
28where
29 T: JsonLike,
30{
31 type Data = T;
32
33 fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
34 data.flat_map_slice(|data, pref| data.itre(pref))
35 }
36}
37
38pub struct IdentityPath<T> {
40 _t: std::marker::PhantomData<T>,
41}
42
43impl<T> Default for IdentityPath<T> {
44 fn default() -> Self {
45 Self::new()
46 }
47}
48
49impl<T> IdentityPath<T> {
50 pub fn new() -> Self {
51 Self {
52 _t: std::marker::PhantomData,
53 }
54 }
55}
56
57impl<'a, T> Path<'a> for IdentityPath<T> {
58 type Data = T;
59
60 fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
61 vec![data]
62 }
63}
64
65pub(crate) struct EmptyPath<T> {
66 _t: std::marker::PhantomData<T>,
67}
68
69impl<'a, T> Path<'a> for EmptyPath<T> {
70 type Data = T;
71
72 fn find(&self, _data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
73 vec![]
74 }
75}
76
77pub struct RootPointer<'a, T> {
79 root: &'a T,
80}
81
82impl<'a, T> RootPointer<'a, T> {
83 pub(crate) fn new(root: &'a T) -> RootPointer<'a, T> {
84 RootPointer { root }
85 }
86}
87
88impl<'a, T> Path<'a> for RootPointer<'a, T>
89where
90 T: JsonLike,
91{
92 type Data = T;
93
94 fn find(&self, _data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
95 vec![JsonPathValue::from_root(self.root)]
96 }
97}
98
99pub struct ObjectField<'a, T> {
101 key: &'a str,
102 _t: std::marker::PhantomData<T>,
103}
104
105impl<'a, T> ObjectField<'a, T> {
106 pub(crate) fn new(key: &'a str) -> ObjectField<'a, T> {
107 ObjectField {
108 key,
109 _t: std::marker::PhantomData,
110 }
111 }
112}
113
114impl<T> Clone for ObjectField<'_, T> {
115 fn clone(&self) -> Self {
116 ObjectField::new(self.key)
117 }
118}
119
120impl<'a, T> Path<'a> for ObjectField<'a, T>
121where
122 T: JsonLike,
123{
124 type Data = T;
125
126 fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
127 let take_field = |v: &'a T| v.get(self.key);
128
129 let res = match data {
130 Slice(js, p) => take_field(js)
131 .map(|v| JsonPathValue::new_slice(v, jsp_obj(&p, self.key)))
132 .unwrap_or_else(|| NoValue),
133 _ => NoValue,
134 };
135 vec![res]
136 }
137}
138
139pub enum FnPath<T> {
140 Size { _t: std::marker::PhantomData<T> },
141}
142
143impl<T> FnPath<T> {
144 pub fn new_size() -> Self {
145 FnPath::Size {
146 _t: std::marker::PhantomData,
147 }
148 }
149}
150
151impl<'a, T> Path<'a> for FnPath<T>
152where
153 T: JsonLike,
154{
155 type Data = T;
156
157 fn flat_find(
158 &self,
159 input: Vec<JsonPathValue<'a, Self::Data>>,
160 is_search_length: bool,
161 ) -> Vec<JsonPathValue<'a, Self::Data>> {
162 if JsonPathValue::only_no_value(&input) {
164 return vec![NoValue];
165 }
166 let res = if is_search_length {
167 NewValue(T::init_with_usize(
168 input.iter().filter(|v| v.has_value()).count(),
169 ))
170 } else {
171 match input.first() {
172 Some(v) => match v {
173 NewValue(d) => d.array_len(),
174 Slice(s, _) => s.array_len(),
175 NoValue => NoValue,
176 },
177 None => NoValue,
178 }
179 };
180 vec![res]
181 }
182
183 fn needs_all(&self) -> bool {
184 true
185 }
186}
187
188pub struct DescentWildcard<T> {
190 _t: std::marker::PhantomData<T>,
191}
192
193impl<T> Default for DescentWildcard<T> {
194 fn default() -> Self {
195 Self::new()
196 }
197}
198
199impl<T> DescentWildcard<T> {
200 pub fn new() -> Self {
201 DescentWildcard {
202 _t: std::marker::PhantomData,
203 }
204 }
205}
206
207impl<'a, T> Path<'a> for DescentWildcard<T>
208where
209 T: JsonLike,
210{
211 type Data = T;
212
213 fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
214 data.map_slice(|data, pref| data.deep_flatten(pref))
215 }
216}
217
218pub struct DescentObject<'a, T> {
220 key: &'a str,
221 _t: std::marker::PhantomData<T>,
222}
223
224impl<'a, T> Path<'a> for DescentObject<'a, T>
225where
226 T: JsonLike,
227{
228 type Data = T;
229
230 fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
231 data.flat_map_slice(|data, pref| {
232 let res_col = data.deep_path_by_key(ObjectField::new(self.key), pref.clone());
233 if res_col.is_empty() {
234 vec![NoValue]
235 } else {
236 JsonPathValue::map_vec(res_col)
237 }
238 })
239 }
240}
241
242impl<'a, T> DescentObject<'a, T> {
243 pub fn new(key: &'a str) -> Self {
244 DescentObject {
245 key,
246 _t: std::marker::PhantomData,
247 }
248 }
249}
250
251pub struct Chain<'a, T> {
253 chain: Vec<TopPaths<'a, T>>,
254 is_search_length: bool,
255}
256
257impl<'a, T> Chain<'a, T>
258where
259 T: JsonLike,
260{
261 pub fn new(chain: Vec<TopPaths<'a, T>>, is_search_length: bool) -> Self {
262 Chain {
263 chain,
264 is_search_length,
265 }
266 }
267 pub fn from(chain: &'a [JsonPath<T>], root: &'a T) -> Self {
268 let chain_len = chain.len();
269 let is_search_length = if chain_len > 2 {
270 let mut res = false;
271 res = match chain.get(chain_len - 1).expect("chain element disappeared") {
276 JsonPath::Fn(Function::Length) => {
277 for item in chain.iter() {
278 match (item, res) {
279 (
281 JsonPath::Index(JsonPathIndex::UnionIndex(_))
282 | JsonPath::Index(JsonPathIndex::UnionKeys(_))
283 | JsonPath::Index(JsonPathIndex::Slice(_, _, _))
284 | JsonPath::Index(JsonPathIndex::Filter(_))
285 | JsonPath::Wildcard,
286 false,
287 ) => {
288 res = true;
289 }
290 (JsonPath::Index(JsonPathIndex::Single(_)), true) => {
292 res = false;
293 }
294 (_, _) => {}
295 }
296 }
297 res
298 }
299 _ => false,
300 };
301 res
302 } else {
303 false
304 };
305
306 Chain::new(
307 chain.iter().map(|p| json_path_instance(p, root)).collect(),
308 is_search_length,
309 )
310 }
311}
312
313impl<'a, T> Path<'a> for Chain<'a, T>
314where
315 T: JsonLike,
316{
317 type Data = T;
318
319 fn find(&self, data: JsonPathValue<'a, Self::Data>) -> Vec<JsonPathValue<'a, Self::Data>> {
320 let mut res = vec![data];
321
322 for inst in self.chain.iter() {
323 if inst.needs_all() {
324 res = inst.flat_find(res, self.is_search_length)
325 } else {
326 res = res.into_iter().flat_map(|d| inst.find(d)).collect()
327 }
328 }
329 res
330 }
331}
332
333#[cfg(test)]
334mod tests {
335 use crate::jp_v;
336 use crate::parser::macros::{chain, idx};
337 use crate::parser::model::{JsonPath, JsonPathIndex};
338 use crate::path;
339 use crate::path::top::{json_path_instance, Function, ObjectField, RootPointer};
340 use crate::path::{JsonPathValue, Path};
341 use crate::JsonPathValue::NoValue;
342 use serde_json::json;
343 use serde_json::Value;
344
345 #[test]
346 fn object_test() {
347 let js = json!({"product": {"key":42}});
348 let res_income = jp_v!(&js);
349
350 let key = String::from("product");
351 let mut field = ObjectField::new(&key);
352 let js = json!({"key":42});
353 assert_eq!(
354 field.find(res_income.clone()),
355 vec![jp_v!(&js;".['product']")]
356 );
357
358 let key = String::from("fake");
359 field.key = &key;
360 assert_eq!(field.find(res_income), vec![NoValue]);
361 }
362
363 #[test]
364 fn root_test() {
365 let res_income = json!({"product": {"key":42}});
366
367 let root = RootPointer::<Value>::new(&res_income);
368
369 assert_eq!(root.find(jp_v!(&res_income)), jp_v!(&res_income;"$",))
370 }
371
372 #[test]
373 fn path_instance_test() {
374 let json = json!({"v": {"k":{"f":42,"array":[0,1,2,3,4,5],"object":{"field1":"val1","field2":"val2"}}}});
375 let field1 = path!("v");
376 let field2 = path!("k");
377 let field3 = path!("f");
378 let field4 = path!("array");
379 let field5 = path!("object");
380
381 let path_inst = json_path_instance(&path!($), &json);
382 assert_eq!(path_inst.find(jp_v!(&json)), jp_v!(&json;"$",));
383
384 let path_inst = json_path_instance(&field1, &json);
385 let exp_json =
386 json!({"k":{"f":42,"array":[0,1,2,3,4,5],"object":{"field1":"val1","field2":"val2"}}});
387 assert_eq!(path_inst.find(jp_v!(&json)), jp_v!(&exp_json;".['v']",));
388
389 let chain = chain!(path!($), field1.clone(), field2.clone(), field3);
390
391 let path_inst = json_path_instance(&chain, &json);
392 let exp_json = json!(42);
393 assert_eq!(
394 path_inst.find(jp_v!(&json)),
395 jp_v!(&exp_json;"$.['v'].['k'].['f']",)
396 );
397
398 let chain = chain!(
399 path!($),
400 field1.clone(),
401 field2.clone(),
402 field4.clone(),
403 path!(idx!(3))
404 );
405 let path_inst = json_path_instance(&chain, &json);
406 let exp_json = json!(3);
407 assert_eq!(
408 path_inst.find(jp_v!(&json)),
409 jp_v!(&exp_json;"$.['v'].['k'].['array'][3]",)
410 );
411
412 let index = idx!([1;-1;2]);
413 let chain = chain!(
414 path!($),
415 field1.clone(),
416 field2.clone(),
417 field4.clone(),
418 path!(index)
419 );
420 let path_inst = json_path_instance(&chain, &json);
421 let one = json!(1);
422 let tree = json!(3);
423 assert_eq!(
424 path_inst.find(jp_v!(&json)),
425 jp_v!(&one;"$.['v'].['k'].['array'][1]", &tree;"$.['v'].['k'].['array'][3]")
426 );
427
428 let union = idx!(idx 1,2 );
429 let chain = chain!(
430 path!($),
431 field1.clone(),
432 field2.clone(),
433 field4,
434 path!(union)
435 );
436 let path_inst = json_path_instance(&chain, &json);
437 let tree = json!(1);
438 let two = json!(2);
439 assert_eq!(
440 path_inst.find(jp_v!(&json)),
441 jp_v!(&tree;"$.['v'].['k'].['array'][1]",&two;"$.['v'].['k'].['array'][2]")
442 );
443
444 let union = idx!("field1", "field2");
445 let chain = chain!(path!($), field1.clone(), field2, field5, path!(union));
446 let path_inst = json_path_instance(&chain, &json);
447 let one = json!("val1");
448 let two = json!("val2");
449 assert_eq!(
450 path_inst.find(jp_v!(&json)),
451 jp_v!(
452 &one;"$.['v'].['k'].['object'].['field1']",
453 &two;"$.['v'].['k'].['object'].['field2']")
454 );
455 }
456 #[test]
457 fn path_descent_arr_test() {
458 let json = json!([{"a":1}]);
459 let chain = chain!(path!($), path!(.."a"));
460 let path_inst = json_path_instance(&chain, &json);
461
462 let one = json!(1);
463 let expected_res = jp_v!(&one;"$[0].['a']",);
464 assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
465 }
466 #[test]
467 fn deep_path_test() {
468 use crate::path::JsonLike;
469 let value = json!([1]);
470 let r = value.deep_flatten("".to_string());
471 assert_eq!(r, vec![(&json!(1), "[0]".to_string())])
472 }
473
474 #[test]
475 fn path_descent_w_array_test() {
476 let json = json!(
477 {
478 "key1": [1]
479 });
480 let chain = chain!(path!($), path!(..*));
481 let path_inst = json_path_instance(&chain, &json);
482
483 let arr = json!([1]);
484 let one = json!(1);
485
486 let expected_res = jp_v!(&arr;"$.['key1']",&one;"$.['key1'][0]");
487 assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
488 }
489 #[test]
490 fn path_descent_w_nested_array_test() {
491 let json = json!(
492 {
493 "key2" : [{"a":1},{}]
494 });
495 let chain = chain!(path!($), path!(..*));
496 let path_inst = json_path_instance(&chain, &json);
497
498 let arr2 = json!([{"a": 1},{}]);
499 let obj = json!({"a": 1});
500 let empty = json!({});
501
502 let one = json!(1);
503
504 let expected_res = jp_v!(
505 &arr2;"$.['key2']",
506 &obj;"$.['key2'][0]",
507 &one;"$.['key2'][0].['a']",
508 ∅"$.['key2'][1]"
509 );
510 assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
511 }
512
513 #[test]
514 fn path_descent_w_test() {
515 let json = json!(
516 {
517 "key1": [1],
518 "key2": "key",
519 "key3": {
520 "key1": "key1",
521 "key2": {
522 "key1": {
523 "key1": 0
524 }
525 }
526 }
527 });
528 let chain = chain!(path!($), path!(..*));
529 let path_inst = json_path_instance(&chain, &json);
530
531 let key1 = json!([1]);
532 let one = json!(1);
533 let zero = json!(0);
534 let key = json!("key");
535 let key1_s = json!("key1");
536
537 let key_3 = json!( {
538 "key1": "key1",
539 "key2": {
540 "key1": {
541 "key1": 0
542 }
543 }
544 });
545 let key_sec = json!( {
546 "key1": {
547 "key1": 0
548 }
549 });
550 let key_th = json!( {
551 "key1": 0
552 });
553
554 let expected_res = vec![
555 jp_v!(&key1;"$.['key1']"),
556 jp_v!(&one;"$.['key1'][0]"),
557 jp_v!(&key;"$.['key2']"),
558 jp_v!(&key_3;"$.['key3']"),
559 jp_v!(&key1_s;"$.['key3'].['key1']"),
560 jp_v!(&key_sec;"$.['key3'].['key2']"),
561 jp_v!(&key_th;"$.['key3'].['key2'].['key1']"),
562 jp_v!(&zero;"$.['key3'].['key2'].['key1'].['key1']"),
563 ];
564 assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
565 }
566 #[test]
567 fn path_descent_test() {
568 let json = json!(
569 {
570 "key1": [1,2,3],
571 "key2": "key",
572 "key3": {
573 "key1": "key1",
574 "key2": {
575 "key1": {
576 "key1": 0
577 }
578 }
579 }
580 });
581 let chain = chain!(path!($), path!(.."key1"));
582 let path_inst = json_path_instance(&chain, &json);
583
584 let res1 = json!([1, 2, 3]);
585 let res2 = json!("key1");
586 let res3 = json!({"key1":0});
587 let res4 = json!(0);
588
589 let expected_res = jp_v!(
590 &res1;"$.['key1']",
591 &res2;"$.['key3'].['key1']",
592 &res3;"$.['key3'].['key2'].['key1']",
593 &res4;"$.['key3'].['key2'].['key1'].['key1']",
594 );
595 assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
596 }
597
598 #[test]
599 fn wildcard_test() {
600 let json = json!({
601 "key1": [1,2,3],
602 "key2": "key",
603 "key3": {}
604 });
605
606 let chain = chain!(path!($), path!(*));
607 let path_inst = json_path_instance(&chain, &json);
608
609 let res1 = json!([1, 2, 3]);
610 let res2 = json!("key");
611 let res3 = json!({});
612
613 let expected_res = jp_v!(&res1;"$.['key1']", &res2;"$.['key2']", &res3;"$.['key3']");
614 assert_eq!(path_inst.find(jp_v!(&json)), expected_res)
615 }
616
617 #[test]
618 fn length_test() {
619 let json = json!({
620 "key1": [1,2,3],
621 "key2": "key",
622 "key3": {}
623 });
624
625 let chain = chain!(path!($), path!(*), JsonPath::Fn(Function::Length));
626 let path_inst = json_path_instance(&chain, &json);
627
628 assert_eq!(
629 path_inst.flat_find(vec![jp_v!(&json)], true),
630 vec![jp_v!(json!(3))]
631 );
632
633 let chain = chain!(path!($), path!("key1"), JsonPath::Fn(Function::Length));
634 let path_inst = json_path_instance(&chain, &json);
635 assert_eq!(
636 path_inst.flat_find(vec![jp_v!(&json)], false),
637 vec![jp_v!(json!(3))]
638 );
639 }
640}