ntree_rs/traversal/traverse_mut/
sync.rs

1//! Synchronous traversal implementation.
2
3use crate::{
4    traversal::{macros, TraverseMut},
5    Asynchronous, InPostMut, InPreMut, Node, PrePostMut, Synchronous,
6};
7use std::marker::PhantomData;
8
9impl<'a, T> TraverseMut<'a, T, Synchronous>
10where
11    T: Sync + Send,
12{
13    pub fn into_async(self) -> TraverseMut<'a, T, Asynchronous> {
14        TraverseMut::<'a, T, Asynchronous>::from(self)
15    }
16}
17
18impl<'a, T> TraverseMut<'a, T, Synchronous> {
19    pub(crate) fn new(node: &'a mut Node<T>) -> Self {
20        Self {
21            node,
22            strategy: PhantomData,
23        }
24    }
25
26    macros::for_each!(&mut Node<T>, iter_mut);
27    macros::map!(&mut Node<T>, iter_mut);
28    macros::reduce!(&mut Node<T>, iter_mut);
29    macros::cascade!(&mut Node<T>, iter_mut);
30}
31
32impl<'a, T> InPreMut<'a, T, Synchronous> {
33    macros::map_pre!(&mut Node<T>, iter_mut);
34    macros::cascade!(&mut Node<T>, iter_mut);
35}
36
37impl<'a, T, S> InPostMut<'a, T, S> {
38    macros::reduce!(&mut Node<T>, iter_mut);
39    macros::map_post!(&mut Node<T>, iter_mut);
40
41    /// Determines a closure to be executed in `pre-order` when traversing the tree.
42    pub fn with_pre<R, F>(self, pre: F) -> PrePostMut<'a, T, R, F, Synchronous>
43    where
44        F: FnMut(&mut Node<T>, &R) -> R,
45    {
46        PrePostMut {
47            node: self.node,
48            pre,
49            r: PhantomData,
50            strategy: PhantomData,
51        }
52    }
53}
54
55impl<'a, T, R, F> PrePostMut<'a, T, R, F, Synchronous>
56where
57    F: FnMut(&mut Node<T>, &R) -> R,
58{
59    macros::reduce_pre_post!(&mut Node<T>, iter_mut);
60    macros::map_pre_post!(&mut Node<T>, iter_mut);
61}
62
63#[cfg(test)]
64mod tests {
65    use super::*;
66    use crate::node;
67
68    #[test]
69    fn test_for_each() {
70        let mut root = node!(10_i32, node!(20, node!(40)), node!(30, node!(50)));
71
72        let mut result = Vec::new();
73        root.traverse_mut().for_each(|n| {
74            n.value = n.value.saturating_add(1);
75            result.push(n.value)
76        });
77
78        assert_eq!(result, vec![41, 21, 51, 31, 11]);
79    }
80
81    #[test]
82    fn test_map() {
83        let mut original = node!(1, node!(2, node!(4)), node!(3, node!(5)));
84        let new_root = original.traverse_mut().map(|n| {
85            n.value += 1;
86            n.value % 2 == 0
87        });
88
89        let want = node!(2, node!(3, node!(5)), node!(4, node!(6)));
90        assert_eq!(original, want);
91
92        let want = node!(true, node!(false, node!(false)), node!(true, node!(true)));
93        assert_eq!(new_root.take(), want);
94    }
95
96    #[test]
97    fn test_reduce() {
98        let mut root = node!(10_i32, node!(20, node!(40)), node!(30, node!(50)));
99
100        let sum = root.traverse_mut().reduce(|n, results| {
101            n.value = n.value.saturating_add(1);
102            n.value + results.iter().sum::<i32>()
103        });
104
105        assert_eq!(sum, 155);
106    }
107
108    #[test]
109    fn test_cascade() {
110        let mut root = node!(10, node!(20, node!(40)), node!(30, node!(50)));
111
112        root.traverse_mut().cascade(0, |n, parent_value| {
113            let next = n.value + parent_value;
114            n.value = *parent_value;
115            next
116        });
117
118        let want = node!(0, node!(10, node!(30)), node!(10, node!(40)));
119        assert_eq!(root, want);
120    }
121
122    #[test]
123    fn test_cascade_pre() {
124        let mut root = node!(10, node!(20, node!(40)), node!(30, node!(50)));
125
126        let mut result = Vec::new();
127        root.traverse_mut().pre().cascade(0, |current, parent| {
128            result.push(current.value + *parent);
129            current.value += 1;
130
131            current.value + *parent
132        });
133
134        assert_eq!(result, vec![10, 31, 72, 41, 92]);
135
136        let want = node!(11, node!(21, node!(41)), node!(31, node!(51)));
137        assert_eq!(root, want);
138    }
139
140    #[test]
141    fn test_map_pre() {
142        let mut original = node!(1, node!(2, node!(5)), node!(3, node!(5)));
143        let new_root = original.traverse_mut().pre().map(true, |child, parent| {
144            child.value += 1;
145            *parent && child.value % 2 == 0
146        });
147
148        let want = node!(2, node!(3, node!(6)), node!(4, node!(6)));
149        assert_eq!(original, want);
150
151        let want = node!(true, node!(false, node!(false)), node!(true, node!(true)));
152        assert_eq!(new_root, want);
153    }
154
155    #[test]
156    fn test_reduce_post() {
157        let mut root = node!(10, node!(20, node!(40)), node!(30, node!(50)));
158
159        let mut result = Vec::new();
160        root.traverse_mut().post().reduce(|current, children| {
161            result.push(current.value + children.len());
162            current.value += 1;
163            current.value + children.len()
164        });
165
166        assert_eq!(result, vec![40, 21, 50, 31, 12]);
167
168        let want = node!(11, node!(21, node!(41)), node!(31, node!(51)));
169        assert_eq!(root, want);
170    }
171
172    #[test]
173    fn test_map_post() {
174        let mut original = node!(1, node!(2, node!(5)), node!(3, node!(5)));
175        let new_root = original.traverse_mut().post().map(|current, _| {
176            current.value += 1;
177            current.value % 2 == 0
178        });
179
180        let want = node!(true, node!(false, node!(true)), node!(true, node!(true)));
181        assert_eq!(new_root, want);
182
183        let want = node!(2, node!(3, node!(6)), node!(4, node!(6)));
184        assert_eq!(original, want);
185    }
186
187    #[test]
188    fn test_reduce_pre_post() {
189        let mut root = node!(10, node!(20, node!(40)), node!(30, node!(50)));
190
191        let mut result = Vec::new();
192        root.traverse_mut()
193            .post()
194            .with_pre(|current, base| {
195                current.value += 1;
196                current.value + base
197            })
198            .reduce(0, |current, base, children| {
199                result.push(current.value + children.len() + base);
200                current.value += 1;
201                current.value + children.len() + base
202            });
203
204        assert_eq!(result, vec![114, 54, 144, 74, 24]);
205
206        let want = node!(12, node!(22, node!(42)), node!(32, node!(52)));
207        assert_eq!(root, want);
208    }
209
210    #[test]
211    fn test_map_pre_post() {
212        let mut original = node!(1, node!(2, node!(5)), node!(3, node!(5)));
213
214        let new_root = original
215            .traverse_mut()
216            .post()
217            .with_pre(|current, base| {
218                current.value += 1;
219                current.value + base
220            })
221            .map(0, |current, base, _| {
222                current.value += 1;
223                current.value % 2 != 0 && base % 2 == 0
224            });
225
226        let want = node!(true, node!(false, node!(false)), node!(true, node!(true)));
227        assert_eq!(new_root, want);
228
229        let want = node!(3, node!(4, node!(7)), node!(5, node!(7)));
230        assert_eq!(original, want);
231    }
232}