ntree_rs/traversal/traverse/
sync.rs

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