mod rule; mod source; use anyhow::Result; use log::{debug, warn}; use rule::Rule; use source::Source; use std::collections::HashSet; pub struct List { pub is_enabled: bool, pub rules: HashSet, pub source: Source, } impl List { pub async fn init(src: &str, is_enabled: bool) -> Result { let source = Source::from_str(src)?; let mut rules = HashSet::new(); load(&mut rules, &source).await?; Ok(Self { rules, source, is_enabled, }) } /// Change rule set status pub async fn set_enabled(&mut self, is_enabled: bool) -> Result { let was_enabled = self.is_enabled; self.is_enabled = is_enabled; if self.is_enabled { debug!("List `{}` enabled", &self.source); } else { debug!("List `{}` disabled", &self.source); } Ok(was_enabled) } /// Reload rule set from it source pub async fn reload(&mut self) -> Result<()> { self.rules.clear(); load(&mut self.rules, &self.source).await?; Ok(()) } /// Check if rule is exist in the index pub fn contains(&self, value: &str) -> bool { self.is_enabled && self.rules.iter().any(|rule| rule.contains(value)) } } async fn load(rules: &mut HashSet, source: &Source) -> Result<()> { debug!("Load list `{source}`..."); for line in source.get().await?.lines() { if line.starts_with("/") || line.starts_with("#") || line.is_empty() { continue; // skip comments } if !rules.insert(Rule::from_line(line)) { warn!("List `{source}` contains duplicated entry: `{line}`") } } Ok(()) }