use std::fmt;
use std::sync::Arc;
use arc_swap::ArcSwap;
use crate::http::HttpResponse;
use crate::types::{WafClassifier, WafClassifyError, WafSignal};
pub(crate) mod matcher;
pub(crate) mod rules;
pub(crate) mod watch;
#[cfg(test)]
mod tests;
pub use rules::{Rules, RulesError, load_from_str};
pub use watch::{WatchError, WatchHandle};
pub struct TomlClassifier {
rules: ArcSwap<Rules>,
}
impl fmt::Debug for TomlClassifier {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
let loaded = self.rules.load();
formatter
.debug_struct("TomlClassifier")
.field("fingerprint_count", &loaded.fingerprints.len())
.finish()
}
}
impl TomlClassifier {
pub fn builtin() -> Self {
Self {
rules: ArcSwap::from_pointee(Rules::builtin()),
}
}
pub fn from_rules(rules: Rules) -> Self {
Self {
rules: ArcSwap::from_pointee(rules),
}
}
pub fn swap(&self, rules: Rules) {
self.rules.store(Arc::new(rules));
}
pub fn watch(self: &Arc<Self>, path: impl AsRef<std::path::Path>) -> Result<WatchHandle, WatchError> {
watch::start_watch(Arc::clone(self), path.as_ref())
}
}
impl WafClassifier for TomlClassifier {
fn classify(&self, response: &HttpResponse) -> Result<Option<WafSignal>, WafClassifyError> {
self.rules.load().classify(response)
}
}