implement in-memory ruleset update

This commit is contained in:
postscriptum 2026-03-22 09:18:09 +02:00
parent b03bdd0e3a
commit 30a77072ed
4 changed files with 85 additions and 32 deletions

View file

@ -1,6 +1,7 @@
use anyhow::Result;
use log::*;
use std::collections::HashSet;
use tokio::sync::RwLock;
#[derive(PartialEq, Eq, Hash)]
pub enum Item {
@ -8,8 +9,20 @@ pub enum Item {
Exact(String),
}
impl Item {
pub fn from_line(rule: &str) -> Self {
if let Some(item) = rule.strip_prefix(".") {
debug!("Add `{rule}` to the whitelist");
Self::Ending(item.to_string())
} else {
debug!("Add `{rule}` exact match to the whitelist");
Self::Exact(rule.to_string())
}
}
}
pub enum List {
Allow(HashSet<Item>),
Allow(RwLock<HashSet<Item>>),
}
impl List {
@ -26,31 +39,40 @@ impl List {
if line.starts_with("/") || line.starts_with("#") || line.is_empty() {
continue;
}
if !this.insert(if let Some(item) = line.strip_prefix(".") {
debug!("Add `{line}` to the whitelist");
Item::Ending(item.to_string())
} else {
debug!("Add `{line}` exact match to the whitelist");
Item::Exact(line.to_string())
}) {
if !this.insert(Item::from_line(line)) {
warn!("Duplicated whitelist record: `{line}`")
}
}
}
info!("Total whitelist entries parsed: {}", this.len());
Ok(Self::Allow(this))
Ok(Self::Allow(RwLock::new(this)))
}
pub fn has(&self, value: &str) -> bool {
pub async fn any(&self, values: &[&str]) -> bool {
match self {
Self::Allow(list) => list.iter().any(|item| match item {
Item::Exact(s) => s == value,
Item::Ending(s) => value.ends_with(s),
}),
Self::Allow(list) => {
let guard = list.read().await;
values.iter().any(|&value| {
guard.iter().any(|item| match item {
Item::Exact(v) => v == value,
Item::Ending(v) => value.ends_with(v),
})
})
}
}
}
pub fn entries(&self) -> usize {
pub async fn entries(&self) -> u64 {
match self {
Self::Allow(list) => list.len(),
Self::Allow(list) => list.read().await.len() as u64,
}
}
pub async fn allow(&self, rule: &str) -> bool {
match self {
List::Allow(list) => list.write().await.insert(Item::from_line(rule)),
}
}
pub async fn block(&self, rule: &str) -> bool {
match self {
List::Allow(list) => list.write().await.remove(&Item::from_line(rule)),
}
}
}