use super::{FileTypeProfile, Processor};
use crate::error::Result;
use crate::store::MappingStore;
use std::collections::HashMap;
use std::sync::Arc;
pub struct ProcessorRegistry {
processors: HashMap<String, Arc<dyn Processor>>,
}
impl ProcessorRegistry {
#[must_use]
pub fn new() -> Self {
Self {
processors: HashMap::new(),
}
}
#[must_use]
pub fn with_builtins() -> Self {
let mut reg = Self::new();
reg.register(Arc::new(super::key_value::KeyValueProcessor));
reg.register(Arc::new(super::json_proc::JsonProcessor));
reg.register(Arc::new(super::yaml_proc::YamlProcessor));
reg.register(Arc::new(super::xml_proc::XmlProcessor));
reg.register(Arc::new(super::csv_proc::CsvProcessor));
reg.register(Arc::new(super::toml_proc::TomlProcessor));
reg.register(Arc::new(super::env_proc::EnvProcessor));
reg.register(Arc::new(super::ini_proc::IniProcessor));
reg.register(Arc::new(super::log_line::LogLineProcessor::new()));
reg
}
pub fn register(&mut self, processor: Arc<dyn Processor>) {
self.processors
.insert(processor.name().to_string(), processor);
}
pub fn get(&self, name: &str) -> Option<&Arc<dyn Processor>> {
self.processors.get(name)
}
pub fn names(&self) -> Vec<&str> {
self.processors.keys().map(|s| s.as_str()).collect()
}
#[must_use]
pub fn len(&self) -> usize {
self.processors.len()
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.processors.is_empty()
}
pub fn find_processor(
&self,
content: &[u8],
profile: &FileTypeProfile,
) -> Option<&Arc<dyn Processor>> {
if let Some(proc) = self.processors.get(&profile.processor) {
if proc.can_handle(content, profile) {
return Some(proc);
}
}
self.processors
.values()
.find(|proc| proc.can_handle(content, profile))
}
pub fn process(
&self,
content: &[u8],
profile: &FileTypeProfile,
store: &MappingStore,
) -> Result<Option<Vec<u8>>> {
match self.find_processor(content, profile) {
Some(proc) => {
let output = proc.process(content, profile, store)?;
Ok(Some(output))
}
None => Ok(None),
}
}
}
impl Default for ProcessorRegistry {
fn default() -> Self {
Self::with_builtins()
}
}