nginx_discovery/ast/
mod.rs1mod directive;
28mod span;
29mod value;
30
31pub use directive::{Directive, DirectiveItem};
32pub use span::{Span, Spanned};
33pub use value::Value;
34
35#[derive(Debug, Clone, PartialEq)]
39#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
40pub struct Config {
41 pub directives: Vec<Directive>,
43}
44
45impl Config {
46 #[must_use]
57 pub fn new() -> Self {
58 Self {
59 directives: Vec::new(),
60 }
61 }
62
63 #[must_use]
77 pub fn with_directives(directives: Vec<Directive>) -> Self {
78 Self { directives }
79 }
80
81 pub fn add_directive(&mut self, directive: Directive) {
83 self.directives.push(directive);
84 }
85
86 #[must_use]
102 pub fn find_directives(&self, name: &str) -> Vec<&Directive> {
103 self.directives
104 .iter()
105 .filter(|d| d.name() == name)
106 .collect()
107 }
108
109 pub fn find_directives_mut(&mut self, name: &str) -> Vec<&mut Directive> {
111 self.directives
112 .iter_mut()
113 .filter(|d| d.name() == name)
114 .collect()
115 }
116
117 #[must_use]
144 pub fn find_directives_recursive(&self, name: &str) -> Vec<&Directive> {
145 let mut result = Vec::new();
146 self.find_directives_recursive_impl(name, &mut result);
147 result
148 }
149
150 fn find_directives_recursive_impl<'a>(&'a self, name: &str, result: &mut Vec<&'a Directive>) {
151 for directive in &self.directives {
152 if directive.name() == name {
154 result.push(directive);
155 }
156 if let Some(children) = directive.children() {
158 for child in children {
159 Self::find_directive_recursive(child, name, result);
160 }
161 }
162 }
163 }
164
165 fn find_directive_recursive<'a>(
167 directive: &'a Directive,
168 name: &str,
169 result: &mut Vec<&'a Directive>,
170 ) {
171 if directive.name() == name {
172 result.push(directive);
173 }
174 if let Some(children) = directive.children() {
175 for child in children {
176 Self::find_directive_recursive(child, name, result);
177 }
178 }
179 }
180
181 #[must_use]
183 pub fn count_directives(&self) -> usize {
184 let mut count = self.directives.len();
185 for directive in &self.directives {
186 if let Some(children) = directive.children() {
187 let child_config = Config {
188 directives: children.to_vec(),
189 };
190 count += child_config.count_directives();
191 }
192 }
193 count
194 }
195
196 #[must_use]
198 pub fn is_empty(&self) -> bool {
199 self.directives.is_empty()
200 }
201}
202
203impl Default for Config {
204 fn default() -> Self {
205 Self::new()
206 }
207}
208
209#[cfg(test)]
210mod tests {
211 use super::*;
212
213 #[test]
214 fn test_config_new() {
215 let config = Config::new();
216 assert!(config.directives.is_empty());
217 assert!(config.is_empty());
218 }
219
220 #[test]
221 fn test_config_with_directives() {
222 let directives = vec![
223 Directive::simple("user", vec!["nginx".to_string()]),
224 Directive::simple("worker_processes", vec!["auto".to_string()]),
225 ];
226 let config = Config::with_directives(directives);
227 assert_eq!(config.directives.len(), 2);
228 assert!(!config.is_empty());
229 }
230
231 #[test]
232 fn test_config_add_directive() {
233 let mut config = Config::new();
234 config.add_directive(Directive::simple("user", vec!["nginx".to_string()]));
235 assert_eq!(config.directives.len(), 1);
236 }
237
238 #[test]
239 fn test_find_directives() {
240 let config = Config::with_directives(vec![
241 Directive::simple("user", vec!["nginx".to_string()]),
242 Directive::simple("worker_processes", vec!["auto".to_string()]),
243 Directive::simple("user", vec!["www-data".to_string()]),
244 ]);
245
246 let users = config.find_directives("user");
247 assert_eq!(users.len(), 2);
248 }
249
250 #[test]
251 fn test_find_directives_recursive() {
252 let location = Directive::block(
253 "location",
254 vec!["/".to_string()],
255 vec![Directive::simple(
256 "access_log",
257 vec!["/var/log/1.log".to_string()],
258 )],
259 );
260
261 let server = Directive::block("server", vec![], vec![location]);
262
263 let config = Config::with_directives(vec![
264 Directive::simple("access_log", vec!["/var/log/main.log".to_string()]),
265 server,
266 ]);
267
268 let logs = config.find_directives_recursive("access_log");
269 assert_eq!(logs.len(), 2);
270 }
271
272 #[test]
273 fn test_count_directives() {
274 let location = Directive::block(
275 "location",
276 vec!["/".to_string()],
277 vec![Directive::simple(
278 "proxy_pass",
279 vec!["http://backend".to_string()],
280 )],
281 );
282
283 let server = Directive::block("server", vec![], vec![location]);
284
285 let config = Config::with_directives(vec![
286 Directive::simple("user", vec!["nginx".to_string()]),
287 server,
288 ]);
289
290 assert_eq!(config.count_directives(), 4);
292 }
293
294 #[test]
295 fn test_config_default() {
296 let config = Config::default();
297 assert!(config.is_empty());
298 }
299}