use std::sync::Arc;
use arc_swap::ArcSwap;
use crate::scan_cache::{self, ScanCache};
use crate::{CompiledRules, Engine, EntityRecognizer, MemoryVault, Options, Recorder, RulesError, RulesFile, Vault};
#[must_use]
pub struct EngineBuilder {
rules: Rules,
options: Options,
recognizer: Option<Arc<dyn EntityRecognizer>>,
vault: Option<Arc<dyn Vault>>,
recorder: Option<Arc<dyn Recorder>>,
scan_cache_bytes: usize,
}
enum Rules {
File(RulesFile),
Compiled(CompiledRules),
}
impl Default for EngineBuilder {
fn default() -> Self {
EngineBuilder {
rules: Rules::File(RulesFile::default()),
options: Options::default(),
recognizer: None,
vault: None,
recorder: None,
scan_cache_bytes: scan_cache::DEFAULT_BUDGET,
}
}
}
impl EngineBuilder {
pub fn rules(mut self, rules: RulesFile) -> Self {
self.rules = Rules::File(rules);
self
}
pub fn options(mut self, options: Options) -> Self {
self.options = options;
self
}
pub fn recognizer(mut self, recognizer: Arc<dyn EntityRecognizer>) -> Self {
self.recognizer = Some(recognizer);
self
}
pub fn compiled_rules(mut self, rules: CompiledRules) -> Self {
self.rules = Rules::Compiled(rules);
self
}
pub fn vault(mut self, vault: Arc<dyn Vault>) -> Self {
self.vault = Some(vault);
self
}
pub fn recorder(mut self, recorder: Arc<dyn Recorder>) -> Self {
self.recorder = Some(recorder);
self
}
pub fn scan_cache_bytes(mut self, bytes: usize) -> Self {
self.scan_cache_bytes = bytes;
self
}
pub fn build(self) -> Result<Engine, RulesError> {
let rules = match self.rules {
Rules::File(file) => CompiledRules::compile(&file, &self.options, self.recognizer)?,
Rules::Compiled(compiled) => compiled,
};
Ok(Engine {
rules: ArcSwap::from_pointee(rules),
vault: self.vault.unwrap_or_else(|| Arc::new(MemoryVault::default())),
recorder: self.recorder,
scans: ScanCache::new(self.scan_cache_bytes),
})
}
}