mod directive;
mod span;
mod value;
pub use directive::{Directive, DirectiveItem};
pub use span::{Span, Spanned};
pub use value::Value;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Config {
pub directives: Vec<Directive>,
}
impl Config {
#[must_use]
pub fn new() -> Self {
Self {
directives: Vec::new(),
}
}
#[must_use]
pub fn with_directives(directives: Vec<Directive>) -> Self {
Self { directives }
}
pub fn add_directive(&mut self, directive: Directive) {
self.directives.push(directive);
}
#[must_use]
pub fn find_directives(&self, name: &str) -> Vec<&Directive> {
self.directives
.iter()
.filter(|d| d.name() == name)
.collect()
}
pub fn find_directives_mut(&mut self, name: &str) -> Vec<&mut Directive> {
self.directives
.iter_mut()
.filter(|d| d.name() == name)
.collect()
}
#[must_use]
pub fn find_directives_recursive(&self, name: &str) -> Vec<&Directive> {
let mut result = Vec::new();
self.find_directives_recursive_impl(name, &mut result);
result
}
fn find_directives_recursive_impl<'a>(&'a self, name: &str, result: &mut Vec<&'a Directive>) {
for directive in &self.directives {
if directive.name() == name {
result.push(directive);
}
if let Some(children) = directive.children() {
for child in children {
Self::find_directive_recursive(child, name, result);
}
}
}
}
fn find_directive_recursive<'a>(
directive: &'a Directive,
name: &str,
result: &mut Vec<&'a Directive>,
) {
if directive.name() == name {
result.push(directive);
}
if let Some(children) = directive.children() {
for child in children {
Self::find_directive_recursive(child, name, result);
}
}
}
#[must_use]
pub fn count_directives(&self) -> usize {
let mut count = self.directives.len();
for directive in &self.directives {
if let Some(children) = directive.children() {
let child_config = Config {
directives: children.to_vec(),
};
count += child_config.count_directives();
}
}
count
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.directives.is_empty()
}
}
impl Default for Config {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_config_new() {
let config = Config::new();
assert!(config.directives.is_empty());
assert!(config.is_empty());
}
#[test]
fn test_config_with_directives() {
let directives = vec![
Directive::simple("user", vec!["nginx".to_string()]),
Directive::simple("worker_processes", vec!["auto".to_string()]),
];
let config = Config::with_directives(directives);
assert_eq!(config.directives.len(), 2);
assert!(!config.is_empty());
}
#[test]
fn test_config_add_directive() {
let mut config = Config::new();
config.add_directive(Directive::simple("user", vec!["nginx".to_string()]));
assert_eq!(config.directives.len(), 1);
}
#[test]
fn test_find_directives() {
let config = Config::with_directives(vec![
Directive::simple("user", vec!["nginx".to_string()]),
Directive::simple("worker_processes", vec!["auto".to_string()]),
Directive::simple("user", vec!["www-data".to_string()]),
]);
let users = config.find_directives("user");
assert_eq!(users.len(), 2);
}
#[test]
fn test_find_directives_recursive() {
let location = Directive::block(
"location",
vec!["/".to_string()],
vec![Directive::simple(
"access_log",
vec!["/var/log/1.log".to_string()],
)],
);
let server = Directive::block("server", vec![], vec![location]);
let config = Config::with_directives(vec![
Directive::simple("access_log", vec!["/var/log/main.log".to_string()]),
server,
]);
let logs = config.find_directives_recursive("access_log");
assert_eq!(logs.len(), 2);
}
#[test]
fn test_count_directives() {
let location = Directive::block(
"location",
vec!["/".to_string()],
vec![Directive::simple(
"proxy_pass",
vec!["http://backend".to_string()],
)],
);
let server = Directive::block("server", vec![], vec![location]);
let config = Config::with_directives(vec![
Directive::simple("user", vec!["nginx".to_string()]),
server,
]);
assert_eq!(config.count_directives(), 4);
}
#[test]
fn test_config_default() {
let config = Config::default();
assert!(config.is_empty());
}
}