diff options
Diffstat (limited to 'vendor/jsonpath_lib/src/select/value_walker.rs')
-rw-r--r-- | vendor/jsonpath_lib/src/select/value_walker.rs | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/vendor/jsonpath_lib/src/select/value_walker.rs b/vendor/jsonpath_lib/src/select/value_walker.rs new file mode 100644 index 000000000..e7b4de0e0 --- /dev/null +++ b/vendor/jsonpath_lib/src/select/value_walker.rs @@ -0,0 +1,99 @@ +use serde_json::Value; +use std::collections::HashSet; + +pub(super) struct ValueWalker; + +impl<'a> ValueWalker { + pub fn all_with_num(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, index: f64) { + Self::walk(vec, tmp, &|v| if v.is_array() { + if let Some(item) = v.get(index as usize) { + Some(vec![item]) + } else { + None + } + } else { + None + }); + } + + pub fn all_with_str(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, key: &str, is_filter: bool) { + if is_filter { + Self::walk(vec, tmp, &|v| match v { + Value::Object(map) if map.contains_key(key) => Some(vec![v]), + _ => None, + }); + } else { + Self::walk(vec, tmp, &|v| match v { + Value::Object(map) => match map.get(key) { + Some(v) => Some(vec![v]), + _ => None, + }, + _ => None, + }); + } + } + + pub fn all(vec: &[&'a Value], tmp: &mut Vec<&'a Value>) { + Self::walk(vec, tmp, &|v| match v { + Value::Array(vec) => Some(vec.iter().collect()), + Value::Object(map) => { + let mut tmp = Vec::new(); + for (_, v) in map { + tmp.push(v); + } + Some(tmp) + } + _ => None, + }); + } + + fn walk<F>(vec: &[&'a Value], tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option<Vec<&Value>> { + for v in vec { + Self::_walk(v, tmp, fun); + } + } + + fn _walk<F>(v: &'a Value, tmp: &mut Vec<&'a Value>, fun: &F) where F: Fn(&Value) -> Option<Vec<&Value>> { + if let Some(mut ret) = fun(v) { + tmp.append(&mut ret); + } + + match v { + Value::Array(vec) => { + for v in vec { + Self::_walk(v, tmp, fun); + } + } + Value::Object(map) => { + for (_, v) in map { + Self::_walk(&v, tmp, fun); + } + } + _ => {} + } + } + + pub fn walk_dedup(v: &'a Value, + tmp: &mut Vec<&'a Value>, + key: &str, + visited: &mut HashSet<*const Value>, ) { + match v { + Value::Object(map) => { + if map.contains_key(key) { + let ptr = v as *const Value; + if !visited.contains(&ptr) { + visited.insert(ptr); + tmp.push(v) + } + } + } + Value::Array(vec) => { + for v in vec { + Self::walk_dedup(v, tmp, key, visited); + } + } + _ => {} + } + } +} + |