jsonpath_lib2 0.3.3

An updated fork of jsonpath_lib. The original crate has not been updated since 2021 Jun 03. It is JsonPath engine written in Rust. It provide a similar API interface in Webassembly and Javascript too. - Webassembly Demo: https://freestrings.github.io/jsonpath Feel free to transfer maintenance for this crate if I don't respond for one year. I consent to the transfer of this crate to the first person who asks help@crates.io for it.
Documentation
use std::collections::HashSet;

use super::utils;
use crate::selector::utils::PathKey;
use serde_json::Value;

pub(super) struct ValueWalker;

impl<'a> ValueWalker {
    pub fn next_all(vec: &[&'a Value]) -> Vec<&'a Value> {
        vec.iter().fold(Vec::new(), |mut acc, v| {
            match v {
                Value::Object(map) => acc.extend(map.values()),
                Value::Array(vec) => acc.extend(vec),
                _ => {}
            }
            acc
        })
    }

    pub fn next_with_str(vec: &[&'a Value], key: &'a str) -> Vec<&'a Value> {
        vec.iter().fold(Vec::new(), |mut acc, v| {
            if let Value::Object(map) = v {
                if let Some(v) = map.get(key) {
                    acc.push(v);
                }
            }
            acc
        })
    }

    pub fn next_with_num(vec: &[&'a Value], index: f64) -> Vec<&'a Value> {
        vec.iter().fold(Vec::new(), |mut acc, v| {
            if let Value::Array(vec) = v {
                if let Some(v) = vec.get(utils::abs_index(index as isize, vec.len())) {
                    acc.push(v);
                }
            }
            acc
        })
    }

    pub fn all_with_num(vec: &[&'a Value], index: f64) -> Vec<&'a Value> {
        Self::walk(vec, &|v, acc| {
            if v.is_array() {
                if let Some(v) = v.get(index as usize) {
                    acc.push(v);
                }
            }
        })
    }

    pub fn all_with_str(vec: &[&'a Value], key: &'a str) -> Vec<&'a Value> {
        let path_key = utils::to_path_str(key);
        Self::walk(vec, &|v, acc| {
            if let Value::Object(map) = v {
                if let Some(v) = map.get(path_key.get_key()) {
                    acc.push(v);
                }
            }
        })
    }

    pub fn all_with_strs(vec: &[&'a Value], keys: &[&'a str]) -> Vec<&'a Value> {
        let path_keys: &Vec<PathKey> = &keys.iter().map(|key| utils::to_path_str(key)).collect();
        vec.iter().fold(Vec::new(), |mut acc, v| {
            if let Value::Object(map) = v {
                path_keys.iter().for_each(|pk| {
                    if let Some(v) = map.get(pk.get_key()) {
                        acc.push(v)
                    }
                });
            }
            acc
        })
    }

    pub fn all(vec: &[&'a Value]) -> Vec<&'a Value> {
        Self::walk(vec, &|v, acc| match v {
            Value::Array(ay) => acc.extend(ay),
            Value::Object(map) => {
                acc.extend(map.values());
            }
            _ => {}
        })
    }

    fn walk<F>(vec: &[&'a Value], fun: &F) -> Vec<&'a Value>
    where
        F: Fn(&'a Value, &mut Vec<&'a Value>),
    {
        vec.iter().fold(Vec::new(), |mut acc, v| {
            Self::_walk(v, &mut acc, fun);
            acc
        })
    }

    fn _walk<F>(v: &'a Value, acc: &mut Vec<&'a Value>, fun: &F)
    where
        F: Fn(&'a Value, &mut Vec<&'a Value>),
    {
        fun(v, acc);

        match v {
            Value::Array(vec) => {
                vec.iter().for_each(|v| Self::_walk(v, acc, fun));
            }
            Value::Object(map) => {
                map.values().for_each(|v| Self::_walk(v, acc, fun));
            }
            _ => {}
        }
    }

    pub fn walk_dedup_all<F1, F2>(
        vec: &[&'a Value],
        key: &str,
        visited: &mut HashSet<*const Value>,
        is_contain: &mut F1,
        is_not_contain: &mut F2,
        depth: usize,
    ) where
        F1: FnMut(&'a Value),
        F2: FnMut(usize),
    {
        vec.iter().enumerate().for_each(|(index, v)| {
            Self::walk_dedup(v, key, visited, index, is_contain, is_not_contain, depth)
        });
    }

    fn walk_dedup<F1, F2>(
        v: &'a Value,
        key: &str,
        visited: &mut HashSet<*const Value>,
        index: usize,
        is_contain: &mut F1,
        is_not_contain: &mut F2,
        depth: usize,
    ) where
        F1: FnMut(&'a Value),
        F2: FnMut(usize),
    {
        let ptr = v as *const Value;
        if visited.contains(&ptr) {
            return;
        }

        match v {
            Value::Object(map) => {
                if map.get(key).is_some() {
                    let ptr = v as *const Value;
                    if !visited.contains(&ptr) {
                        visited.insert(ptr);
                        is_contain(v);
                    }
                } else if depth == 0 {
                    is_not_contain(index);
                }
            }
            Value::Array(vec) => {
                if depth == 0 {
                    is_not_contain(index);
                }
                vec.iter().for_each(|v| {
                    Self::walk_dedup(
                        v,
                        key,
                        visited,
                        index,
                        is_contain,
                        is_not_contain,
                        depth + 1,
                    );
                })
            }
            _ => {
                if depth == 0 {
                    is_not_contain(index);
                }
            }
        }
    }
}