1use serde_json::Value;
2use std::collections::HashSet;
3
4pub(super) struct ValueWalker;
5
6impl<'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