serde_json_merge/iter/
mod.rs

1pub mod dfs;
2use super::{Index, IndexPath};
3use serde_json::Value;
4
5#[cfg(feature = "rayon")]
6pub trait ParallelTraverser: Sized {
7    fn split(&mut self) -> Option<Self>;
8}
9
10pub trait Traverser {
11    fn new() -> Self;
12
13    fn set_limit<L>(&mut self, limit: L)
14    where
15        L: Into<Option<usize>>;
16
17    fn set_depth<D>(&mut self, depth: D)
18    where
19        D: Into<Option<usize>>;
20
21    fn mutate_then_next(
22        &mut self,
23        value: &mut Value,
24        mutate: impl FnMut(&IndexPath, &mut Value),
25    ) -> Option<IndexPath>;
26
27    fn next(&mut self, value: &Value) -> Option<IndexPath>;
28
29    fn process_next(
30        &mut self,
31        value: &Value,
32        process: impl FnMut(&IndexPath, Option<&Value>) -> bool,
33    ) -> Option<IndexPath>;
34
35    fn reset(&mut self);
36}
37
38#[allow(clippy::module_name_repetitions)]
39#[derive(Clone)]
40pub struct KeyValueIter<'a, T> {
41    inner: &'a Value,
42    traverser: T,
43}
44
45impl<'a, T> Iterator for KeyValueIter<'a, T>
46where
47    T: Traverser,
48{
49    type Item = (IndexPath, &'a Value);
50
51    #[inline]
52    fn next(&mut self) -> Option<Self::Item> {
53        loop {
54            match self.traverser.next(self.inner).map(|idx| {
55                let value = self.inner.get_index(&idx);
56                (idx, value)
57            }) {
58                Some((idx, Some(value))) => return Some((idx, value)),
59                None => return None,
60                Some(_) => {
61                    // continue
62                }
63            }
64        }
65    }
66}
67
68// #[cfg(feature = "rayon")]
69// impl<'a, T> par_dfs::sync::par::SplittableIterator for KeyValueIter<'a, T>
70// where
71//     T: Traverser + ParallelTraverser,
72// {
73//     fn split(&mut self) -> Option<Self> {
74//         match self.traverser.split() {
75//             Some(split) => Some(Self {
76//                 traverser: split,
77//                 inner: self.inner,
78//             }),
79//             None => None,
80//         }
81//     }
82// }
83
84// #[cfg(feature = "rayon")]
85// impl<'a, T> rayon::iter::IntoParallelIterator for KeyValueIter<'a, T>
86// where
87//     T: Traverser + ParallelTraverser + Send,
88// {
89//     type Iter = par_dfs::sync::par::ParallelSplittableIterator<Self>;
90//     type Item = <Self as Iterator>::Item;
91
92//     fn into_par_iter(self) -> Self::Iter {
93//         par_dfs::sync::par::ParallelSplittableIterator::new(self)
94//     }
95// }
96
97pub struct KeyValueMutator<'a, T> {
98    inner: &'a mut Value,
99    traverser: T,
100}
101
102impl<T> KeyValueMutator<'_, T>
103where
104    T: Traverser,
105{
106    pub fn for_each(&mut self, mut func: impl FnMut(&IndexPath, &mut Value)) {
107        self.traverser.reset();
108        while self
109            .traverser
110            .mutate_then_next(self.inner, &mut func)
111            .is_some()
112        {}
113    }
114}
115
116pub trait Iter {
117    fn iter<T>(&self) -> KeyValueIter<T>
118    where
119        T: Traverser;
120
121    fn mutate<T>(&mut self) -> KeyValueMutator<T>
122    where
123        T: Traverser;
124
125    fn iter_recursive<T>(&self) -> KeyValueIter<T>
126    where
127        T: Traverser;
128
129    fn mutate_recursive<T>(&mut self) -> KeyValueMutator<T>
130    where
131        T: Traverser;
132}
133
134impl Iter for Value {
135    fn iter<T>(&self) -> KeyValueIter<T>
136    where
137        T: Traverser,
138    {
139        let mut traverser = T::new();
140        traverser.set_depth(1);
141        traverser.set_limit(None);
142        KeyValueIter {
143            inner: self,
144            traverser,
145        }
146    }
147
148    fn mutate<T>(&mut self) -> KeyValueMutator<T>
149    where
150        T: Traverser,
151    {
152        let mut traverser = T::new();
153        traverser.set_depth(1);
154        traverser.set_limit(None);
155        KeyValueMutator {
156            inner: self,
157            traverser,
158        }
159    }
160
161    fn iter_recursive<T>(&self) -> KeyValueIter<T>
162    where
163        T: Traverser,
164    {
165        let mut traverser = T::new();
166        traverser.set_depth(None);
167        traverser.set_limit(None);
168        KeyValueIter {
169            inner: self,
170            traverser,
171        }
172    }
173
174    fn mutate_recursive<T>(&mut self) -> KeyValueMutator<T>
175    where
176        T: Traverser,
177    {
178        let mut traverser = T::new();
179        traverser.set_depth(None);
180        traverser.set_limit(None);
181        KeyValueMutator {
182            inner: self,
183            traverser,
184        }
185    }
186}
187
188#[cfg(test)]
189pub mod test {
190    use super::*;
191    use crate::index;
192    use crate::iter::dfs::Dfs;
193    use crate::test::CollectCloned;
194    use pretty_assertions::assert_eq;
195    use serde_json::json;
196
197    #[test]
198    fn nonterminal_value_iter() {
199        let value = json!({
200            "person1": { "name": "bob" },
201            "person2": { "name": "john" },
202        });
203        assert_eq!(
204            value.iter::<Dfs>().collect_cloned(),
205            vec![
206                //  todo: depth 0 should be skipped
207                (index!(), value.clone()),
208                (index!("person1"), json!({ "name": "bob" })),
209                (index!("person2"), json!({ "name": "john" })),
210            ]
211        );
212        // todo: same as bfs
213        assert_eq!(
214            value.iter::<Dfs>().collect_cloned(),
215            value.iter::<Dfs>().collect_cloned()
216        );
217    }
218
219    #[test]
220    fn value_iter_recursive_dfs() {
221        let value = json!({
222            "person1": { "name": "bob" },
223            "person2": { "name": "john" },
224        });
225        assert_eq!(
226            value.iter_recursive::<Dfs>().collect_cloned(),
227            vec![
228                (index!(), value),
229                (index!("person1"), json!({ "name": "bob" })),
230                (index!("person1", "name"), json!("bob")),
231                (index!("person2"), json!({ "name": "john" })),
232                (index!("person2", "name"), json!("john")),
233            ]
234        );
235    }
236}