pub mod dfs;
use super::{Index, IndexPath};
use serde_json::Value;
#[cfg(feature = "rayon")]
pub trait ParallelTraverser: Sized {
fn split(&mut self) -> Option<Self>;
}
pub trait Traverser {
fn new() -> Self;
fn set_limit<L>(&mut self, limit: L)
where
L: Into<Option<usize>>;
fn set_depth<D>(&mut self, depth: D)
where
D: Into<Option<usize>>;
fn mutate_then_next(
&mut self,
value: &mut Value,
mutate: impl FnMut(&IndexPath, &mut Value),
) -> Option<IndexPath>;
fn next(&mut self, value: &Value) -> Option<IndexPath>;
fn process_next(
&mut self,
value: &Value,
process: impl FnMut(&IndexPath, Option<&Value>) -> bool,
) -> Option<IndexPath>;
fn reset(&mut self);
}
#[allow(clippy::module_name_repetitions)]
#[derive(Clone)]
pub struct KeyValueIter<'a, T> {
inner: &'a Value,
traverser: T,
}
impl<'a, T> Iterator for KeyValueIter<'a, T>
where
T: Traverser,
{
type Item = (IndexPath, &'a Value);
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
match self.traverser.next(self.inner).map(|idx| {
let value = self.inner.get_index(&idx);
(idx, value)
}) {
Some((idx, Some(value))) => return Some((idx, value)),
Some(_) => continue,
None => return None,
}
}
}
}
pub struct KeyValueMutator<'a, T> {
inner: &'a mut Value,
traverser: T,
}
impl<'a, T> KeyValueMutator<'a, T>
where
T: Traverser,
{
pub fn for_each(&mut self, mut func: impl FnMut(&IndexPath, &mut Value)) {
self.traverser.reset();
while self
.traverser
.mutate_then_next(self.inner, &mut func)
.is_some()
{}
}
}
pub trait Iter {
fn iter<T>(&self) -> KeyValueIter<T>
where
T: Traverser;
fn mutate<T>(&mut self) -> KeyValueMutator<T>
where
T: Traverser;
fn iter_recursive<T>(&self) -> KeyValueIter<T>
where
T: Traverser;
fn mutate_recursive<T>(&mut self) -> KeyValueMutator<T>
where
T: Traverser;
}
impl Iter for Value {
fn iter<T>(&self) -> KeyValueIter<T>
where
T: Traverser,
{
let mut traverser = T::new();
traverser.set_depth(1);
traverser.set_limit(None);
KeyValueIter {
inner: self,
traverser,
}
}
fn mutate<T>(&mut self) -> KeyValueMutator<T>
where
T: Traverser,
{
let mut traverser = T::new();
traverser.set_depth(1);
traverser.set_limit(None);
KeyValueMutator {
inner: self,
traverser,
}
}
fn iter_recursive<T>(&self) -> KeyValueIter<T>
where
T: Traverser,
{
let mut traverser = T::new();
traverser.set_depth(None);
traverser.set_limit(None);
KeyValueIter {
inner: self,
traverser,
}
}
fn mutate_recursive<T>(&mut self) -> KeyValueMutator<T>
where
T: Traverser,
{
let mut traverser = T::new();
traverser.set_depth(None);
traverser.set_limit(None);
KeyValueMutator {
inner: self,
traverser,
}
}
}
#[cfg(test)]
pub mod test {
use super::*;
use crate::index;
use crate::iter::dfs::Dfs;
use crate::test::CollectCloned;
use pretty_assertions::assert_eq;
use serde_json::json;
#[test]
fn nonterminal_value_iter() {
let value = json!({
"person1": { "name": "bob" },
"person2": { "name": "john" },
});
assert_eq!(
value.iter::<Dfs>().collect_cloned(),
vec![
(index!(), value.clone()),
(index!("person1"), json!({ "name": "bob" })),
(index!("person2"), json!({ "name": "john" })),
]
);
assert_eq!(
value.iter::<Dfs>().collect_cloned(),
value.iter::<Dfs>().collect_cloned()
);
}
#[test]
fn value_iter_recursive_dfs() {
let value = json!({
"person1": { "name": "bob" },
"person2": { "name": "john" },
});
assert_eq!(
value.iter_recursive::<Dfs>().collect_cloned(),
vec![
(index!(), value),
(index!("person1"), json!({ "name": "bob" })),
(index!("person1", "name"), json!("bob")),
(index!("person2"), json!({ "name": "john" })),
(index!("person2", "name"), json!("john")),
]
);
}
}