1 | use serde_json::Value; |
2 | use std::collections::HashSet; |
3 | |
4 | pub(super) struct ValueWalker; |
5 | |
6 | impl<'a> ValueWalker { |
7 | pub fn all_with_num(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, index: f64) { |
8 | Self::walk(vec, tmp, &|v| if v.is_array() { |
9 | v.get(index as usize).map(|item| vec![item]) |
10 | } else { |
11 | None |
12 | }); |
13 | } |
14 | |
15 | pub fn all_with_str(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, key: &str, is_filter: bool) { |
16 | if is_filter { |
17 | Self::walk(vec, tmp, &|v| match v { |
18 | Value::Object(map) if map.contains_key(key) => Some(vec![v]), |
19 | _ => None, |
20 | }); |
21 | } else { |
22 | Self::walk(vec, tmp, &|v| match v { |
23 | Value::Object(map) => map.get(key).map(|v| vec![v]), |
24 | _ => None, |
25 | }); |
26 | } |
27 | } |
28 | |
29 | pub fn all(vec: &[&'a Value], tmp: &mut Vec<&'a Value>) { |
30 | Self::walk(vec, tmp, &|v| match v { |
31 | Value::Array(vec) => Some(vec.iter().collect()), |
32 | Value::Object(map) => { |
33 | let mut tmp = Vec::new(); |
34 | for (_, v) in map { |
35 | tmp.push(v); |
36 | } |
37 | Some(tmp) |
38 | } |
39 | _ => None, |
40 | }); |
41 | } |
42 | |
43 | fn walk<F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option<Vec<&Value>> { |
44 | for v in vec { |
45 | Self::_walk(v, tmp, fun); |
46 | } |
47 | } |
48 | |
49 | fn _walk<F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option<Vec<&Value>> { |
50 | if let Some(mut ret) = fun(v) { |
51 | tmp.append(&mut ret); |
52 | } |
53 | |
54 | match v { |
55 | Value::Array(vec) => { |
56 | for v in vec { |
57 | Self::_walk(v, tmp, fun); |
58 | } |
59 | } |
60 | Value::Object(map) => { |
61 | for (_, v) in map { |
62 | Self::_walk(&v, tmp, fun); |
63 | } |
64 | } |
65 | _ => {} |
66 | } |
67 | } |
68 | |
69 | pub fn walk_dedup(v: &'a Value, |
70 | tmp: &mut Vec<&'a Value>, |
71 | key: &str, |
72 | visited: &mut HashSet<*const Value>, ) { |
73 | match v { |
74 | Value::Object(map) => { |
75 | if map.contains_key(key) { |
76 | let ptr = v as *const Value; |
77 | if !visited.contains(&ptr) { |
78 | visited.insert(ptr); |
79 | tmp.push(v) |
80 | } |
81 | } |
82 | } |
83 | Value::Array(vec) => { |
84 | for v in vec { |
85 | Self::walk_dedup(v, tmp, key, visited); |
86 | } |
87 | } |
88 | _ => {} |
89 | } |
90 | } |
91 | } |
92 | |
93 | |