wp_primitives/scope/
basic.rs1#[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 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 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 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}