use async_trait::async_trait;
use super::regex;
use super::types::ExtractedEntities;
#[async_trait]
pub trait EntityExtractor: Send + Sync {
fn name(&self) -> &'static str;
async fn extract(&self, text: &str) -> anyhow::Result<ExtractedEntities>;
}
pub struct RegexEntityExtractor;
#[async_trait]
impl EntityExtractor for RegexEntityExtractor {
fn name(&self) -> &'static str {
"regex"
}
async fn extract(&self, text: &str) -> anyhow::Result<ExtractedEntities> {
Ok(regex::extract(text))
}
}
pub struct CompositeExtractor {
inner: Vec<Box<dyn EntityExtractor>>,
}
impl CompositeExtractor {
pub fn new(inner: Vec<Box<dyn EntityExtractor>>) -> Self {
Self { inner }
}
pub fn regex_only() -> Self {
Self::new(vec![Box::new(RegexEntityExtractor)])
}
}
#[async_trait]
impl EntityExtractor for CompositeExtractor {
fn name(&self) -> &'static str {
"composite"
}
async fn extract(&self, text: &str) -> anyhow::Result<ExtractedEntities> {
let mut out = ExtractedEntities::default();
for ex in &self.inner {
match ex.extract(text).await {
Ok(batch) => out.merge(batch),
Err(_e) => {
}
}
}
Ok(out)
}
}
#[cfg(test)]
#[path = "composite_tests.rs"]
mod tests;