Skip to main content

wp_primitives/scope/
basic.rs

1/// Evaluator for basic nested scopes with balanced delimiters
2#[derive(Default)]
3pub struct ScopeEval {
4    count: i32,
5    beg: char,
6    end: char,
7    in_scope: bool,
8    end_last: bool,
9}
10impl ScopeEval {
11    #[inline(always)]
12    pub fn new(beg: char, end: char) -> Self {
13        ScopeEval {
14            count: 0,
15            beg,
16            end,
17            in_scope: false,
18            end_last: false,
19        }
20    }
21    #[inline(always)]
22    pub fn in_scope(&mut self, i: char) -> bool {
23        if self.end_last {
24            self.end_last = false;
25            self.in_scope = false;
26        }
27        if self.in_scope {
28            if i == self.end {
29                self.count -= 1;
30                if self.count == 0 {
31                    self.end_last = true;
32                }
33            } else if i == self.beg {
34                self.count += 1;
35            }
36        } else if i == self.beg {
37            self.count += 1;
38            self.in_scope = true;
39        }
40        self.in_scope
41    }
42    #[inline(always)]
43    pub fn len(data: &str, beg: char, end: char) -> usize {
44        let mut op = ScopeEval::new(beg, end);
45        let mut len_size: usize = 0;
46        for x in data.chars() {
47            if op.in_scope(x) {
48                len_size += 1;
49            } else {
50                break;
51            }
52        }
53        len_size
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use super::ScopeEval;
60
61    mod basic_scope {
62        use super::*;
63
64        #[test]
65        fn valid_simple_scope() {
66            let data = r#"(hello)"#;
67            let size = ScopeEval::len(data, '(', ')');
68            assert_eq!(size, 7);
69        }
70
71        #[test]
72        fn invalid_no_opening() {
73            let data = r#"what(hello)"#;
74            let size = ScopeEval::len(data, '(', ')');
75            assert_eq!(size, 0);
76        }
77
78        #[test]
79        fn valid_nested_scope() {
80            let data = r#"(what(hello))"#;
81            let size = ScopeEval::len(data, '(', ')');
82            assert_eq!(size, 13);
83        }
84
85        #[test]
86        fn valid_complex_nested() {
87            let data = r#"(ip(10.0.0.1), ip(10.0.0.10)) => crate(city1) ;
88ip(10.0.10.1)  => crate(city2) ;
89_  => chars(bj) ;
90"#;
91            let size = ScopeEval::len(data, '(', ')');
92            assert_eq!(size, 29);
93        }
94    }
95
96    mod edge_cases {
97        use super::*;
98
99        #[test]
100        fn empty_scope() {
101            let data = "()";
102            let size = ScopeEval::len(data, '(', ')');
103            assert_eq!(size, 2);
104        }
105
106        #[test]
107        fn empty_input() {
108            let data = "";
109            let size = ScopeEval::len(data, '(', ')');
110            assert_eq!(size, 0);
111        }
112
113        #[test]
114        fn only_opening() {
115            let data = "(((";
116            let size = ScopeEval::len(data, '(', ')');
117            // Current implementation doesn't match all closings, returns partial count
118            assert_eq!(size, 3, "Counts opening but no closing found");
119        }
120
121        #[test]
122        fn only_closing() {
123            let data = ")))";
124            let size = ScopeEval::len(data, '(', ')');
125            assert_eq!(size, 0);
126        }
127
128        #[test]
129        fn partial_match() {
130            let data = "(hello)(world)";
131            let size = ScopeEval::len(data, '(', ')');
132            // Current implementation matches both scopes consecutively
133            assert_eq!(size, 14, "Matches both adjacent scopes");
134        }
135
136        #[test]
137        fn mismatched_nesting() {
138            let data = "((hello)";
139            let size = ScopeEval::len(data, '(', ')');
140            // Current implementation returns partial match
141            assert_eq!(size, 8, "Returns length including unmatched bracket");
142        }
143
144        #[test]
145        fn deeply_nested() {
146            let data = "((((inner))))";
147            let size = ScopeEval::len(data, '(', ')');
148            assert_eq!(size, 13);
149        }
150    }
151
152    mod different_delimiters {
153        use super::*;
154
155        #[test]
156        fn curly_braces() {
157            let data = "{key: value}";
158            let size = ScopeEval::len(data, '{', '}');
159            assert_eq!(size, 12);
160        }
161
162        #[test]
163        fn square_brackets() {
164            let data = "[1, 2, 3]";
165            let size = ScopeEval::len(data, '[', ']');
166            assert_eq!(size, 9);
167        }
168
169        #[test]
170        fn angle_brackets() {
171            let data = "<generic>";
172            let size = ScopeEval::len(data, '<', '>');
173            assert_eq!(size, 9);
174        }
175
176        #[test]
177        fn nested_curly_braces() {
178            let data = "{outer: {inner: value}}";
179            let size = ScopeEval::len(data, '{', '}');
180            assert_eq!(size, 23);
181        }
182    }
183
184    mod boundary_conditions {
185        use super::*;
186
187        #[test]
188        fn single_char_content() {
189            let data = "(x)";
190            let size = ScopeEval::len(data, '(', ')');
191            assert_eq!(size, 3);
192        }
193
194        #[test]
195        fn whitespace_only_content() {
196            let data = "(   )";
197            let size = ScopeEval::len(data, '(', ')');
198            assert_eq!(size, 5);
199        }
200
201        #[test]
202        fn newlines_in_content() {
203            let data = "(line1\nline2\nline3)";
204            let size = ScopeEval::len(data, '(', ')');
205            assert_eq!(size, 19);
206        }
207
208        #[test]
209        fn special_chars_in_content() {
210            let data = "(!@#$%^&*)";
211            let size = ScopeEval::len(data, '(', ')');
212            assert_eq!(size, 10);
213        }
214    }
215}