use crate::logger::Level;
#[derive(Debug, Clone)]
pub struct ModuleFilter {
include: Vec<String>,
exclude: Vec<String>,
default_level: Level,
}
impl ModuleFilter {
pub fn new(default_level: Level) -> Self {
Self { include: Vec::new(), exclude: Vec::new(), default_level }
}
pub fn include(mut self, module: impl Into<String>) -> Self {
self.include.push(module.into());
self
}
pub fn include_many(mut self, modules: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.include.extend(modules.into_iter().map(Into::into));
self
}
pub fn exclude(mut self, module: impl Into<String>) -> Self {
self.exclude.push(module.into());
self
}
pub fn exclude_many(mut self, modules: impl IntoIterator<Item = impl Into<String>>) -> Self {
self.exclude.extend(modules.into_iter().map(Into::into));
self
}
pub fn with_default_level(mut self, level: Level) -> Self {
self.default_level = level;
self
}
pub fn should_log(&self, module_path: &str) -> bool {
for excluded in &self.exclude {
if module_path.starts_with(excluded) {
return false;
}
}
if self.include.is_empty() {
return true;
}
for included in &self.include {
if module_path.starts_with(included) {
return true;
}
}
false
}
pub fn default_level(&self) -> Level {
self.default_level
}
}
impl Default for ModuleFilter {
fn default() -> Self {
Self::new(Level::Info)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_filter_allows_all() {
let filter = ModuleFilter::default();
assert!(filter.should_log("bettertui_engine::render"));
assert!(filter.should_log("bettertui_engine::layout"));
assert!(filter.should_log("some_other_crate"));
}
#[test]
fn include_filter() {
let filter = ModuleFilter::new(Level::Info).include("bettertui_engine::render");
assert!(filter.should_log("bettertui_engine::render"));
assert!(filter.should_log("bettertui_engine::render::painter"));
assert!(!filter.should_log("bettertui_engine::layout"));
}
#[test]
fn exclude_filter() {
let filter = ModuleFilter::new(Level::Info).exclude("bettertui_engine::render");
assert!(!filter.should_log("bettertui_engine::render"));
assert!(!filter.should_log("bettertui_engine::render::painter"));
assert!(filter.should_log("bettertui_engine::layout"));
}
#[test]
fn exclude_takes_precedence() {
let filter = ModuleFilter::new(Level::Info).include("bettertui_engine").exclude("bettertui_engine::render");
assert!(!filter.should_log("bettertui_engine::render"));
assert!(!filter.should_log("bettertui_engine::render::painter"));
assert!(filter.should_log("bettertui_engine::layout"));
}
#[test]
fn multiple_includes() {
let filter =
ModuleFilter::new(Level::Info).include_many(vec!["bettertui_engine::render", "bettertui_engine::layout"]);
assert!(filter.should_log("bettertui_engine::render"));
assert!(filter.should_log("bettertui_engine::layout"));
assert!(!filter.should_log("bettertui_engine::event"));
}
#[test]
fn multiple_excludes() {
let filter =
ModuleFilter::new(Level::Info).exclude_many(vec!["bettertui_engine::render", "bettertui_engine::layout"]);
assert!(!filter.should_log("bettertui_engine::render"));
assert!(!filter.should_log("bettertui_engine::layout"));
assert!(filter.should_log("bettertui_engine::event"));
}
#[test]
fn prefix_matching() {
let filter = ModuleFilter::new(Level::Info).include("bettertui_engine::render");
assert!(filter.should_log("bettertui_engine::render"));
assert!(filter.should_log("bettertui_engine::render::painter"));
assert!(filter.should_log("bettertui_engine::render::painter::core"));
assert!(filter.should_log("bettertui_engine::renderer"));
}
#[test]
fn default_level() {
let filter = ModuleFilter::new(Level::Warn);
assert_eq!(filter.default_level(), Level::Warn);
let filter = filter.with_default_level(Level::Debug);
assert_eq!(filter.default_level(), Level::Debug);
}
}