iter_tree/
lib.rs

1#![warn(clippy::all, clippy::pedantic, clippy::nursery, clippy::unwrap_used)]
2#![allow(clippy::module_name_repetitions, clippy::ignored_unit_patterns)]
3#![forbid(unsafe_code)]
4#![doc = include_str!("../DOC.md")]
5
6mod nesting_function;
7#[cfg(feature = "vec")]
8mod tree;
9#[cfg(feature = "deque")]
10mod tree_deque;
11
12pub use nesting_function::*;
13#[cfg(feature = "vec")]
14pub use tree::*;
15#[cfg(feature = "deque")]
16pub use tree_deque::*;
17
18#[cfg(test)]
19mod tests {
20    #![allow(unused)]
21    use super::{Nesting, NestingFunction};
22
23    #[derive(Debug, Default)]
24    struct StackController<T> {
25        stack: Vec<T>,
26    }
27
28    impl<T> StackController<T> {
29        pub fn is_empty(&self) -> bool {
30            self.stack.is_empty()
31        }
32    }
33
34    impl NestingFunction<char> for &mut StackController<char> {
35        fn direction(&mut self, item: &char) -> Nesting {
36            let &c = item;
37            match c {
38                '<' | '(' => {
39                    self.stack.push(c);
40                    Nesting::Increase
41                }
42                '>' =>
43                {
44                    #[allow(clippy::unwrap_used)]
45                    if !self.stack.is_empty() && self.stack.last().unwrap() == &'<' {
46                        self.stack.pop();
47                        Nesting::Decrease
48                    } else {
49                        Nesting::Maintain
50                    }
51                }
52                ')' =>
53                {
54                    #[allow(clippy::unwrap_used)]
55                    if !self.stack.is_empty() && self.stack.last().unwrap() == &'(' {
56                        self.stack.pop();
57                        Nesting::Decrease
58                    } else {
59                        Nesting::Maintain
60                    }
61                }
62                _ => Nesting::Maintain,
63            }
64        }
65    }
66
67    #[cfg(feature = "vec")]
68    mod vec {
69        use super::*;
70        use crate::{IntoTreeExt, Tree};
71
72        #[test]
73        fn basic() {
74            let tree: Tree<char> = "a * ( (d + b) * c ) + e"
75                .chars()
76                .filter(|&c: &char| !c.is_whitespace())
77                .into_tree(|&c: &char| match c {
78                    '(' => Nesting::Increase,
79                    ')' => Nesting::Decrease,
80                    _ => Nesting::Maintain,
81                });
82
83            println!("{tree:#?}");
84        }
85
86        #[test]
87        fn iter() {
88            let before = String::from("a+(b+c)+d");
89
90            let tree = before.chars().into_tree(|&item: &char| match item {
91                '(' => Nesting::Increase,
92                ')' => Nesting::Decrease,
93                _ => Nesting::Maintain,
94            });
95
96            let after: String = tree.into_iter().collect();
97
98            assert_eq!(before, after);
99        }
100
101        #[test]
102        fn with_fn_mut() {
103            let mut depth = 0;
104
105            let tree: Tree<char> = "a+(b+c)+d".chars().into_tree(|&item: &char| match item {
106                '(' => {
107                    depth += 1;
108                    Nesting::Increase
109                }
110                ')' => {
111                    depth -= 1;
112                    Nesting::Decrease
113                }
114                _ => Nesting::Maintain,
115            });
116
117            assert!(depth == 0);
118
119            println!("{tree:#?}");
120        }
121
122        #[test]
123        fn correct_stack() {
124            let mut parser = StackController::default();
125
126            let td = "< ( < > ) >"
127                .chars()
128                .filter(|c| !c.is_whitespace())
129                .into_tree(&mut parser);
130
131            println!("{td:#?}");
132
133            assert!(parser.is_empty());
134        }
135
136        #[test]
137        fn incorrect_stack() {
138            let mut parser = StackController::default();
139
140            let td = "<(>)".chars().into_tree(&mut parser);
141
142            println!("{td:#?}");
143
144            assert!(!parser.is_empty());
145        }
146    }
147
148    #[cfg(feature = "deque")]
149    mod deque {
150        use super::*;
151        use crate::{IntoTreeDequeExt, TreeDeque};
152
153        #[test]
154        fn basic() {
155            let tree: TreeDeque<char> = "a * ( (d + b) * c ) + e"
156                .chars()
157                .filter(|&c: &char| !c.is_whitespace())
158                .into_tree_deque(|&c: &char| match c {
159                    '(' => Nesting::Increase,
160                    ')' => Nesting::Decrease,
161                    _ => Nesting::Maintain,
162                });
163
164            println!("{tree:#?}");
165        }
166
167        #[test]
168        fn iter() {
169            let before = String::from("a+(b+c)+d");
170
171            let tree = before.chars().into_tree_deque(|&item: &char| match item {
172                '(' => Nesting::Increase,
173                ')' => Nesting::Decrease,
174                _ => Nesting::Maintain,
175            });
176
177            let after: String = tree.into_iter().collect();
178
179            assert_eq!(before, after);
180        }
181
182        #[test]
183        fn correct_stack() {
184            let mut parser = StackController::default();
185
186            let td = "< ( < > ) >"
187                .chars()
188                .filter(|c| !c.is_whitespace())
189                .into_tree_deque(&mut parser);
190
191            println!("{td:#?}");
192
193            assert!(parser.is_empty());
194        }
195
196        #[test]
197        fn incorrect_stack() {
198            let mut parser = StackController::default();
199
200            let td = "<(>)".chars().into_tree_deque(&mut parser);
201
202            println!("{td:#?}");
203
204            assert!(!parser.is_empty());
205        }
206    }
207}