use crate::matcher::Matcher;
use async_trait::async_trait;
use rusmes_proto::{Mail, MailAddress};
use std::sync::Arc;
pub struct AndMatcher {
matchers: Vec<Arc<dyn Matcher>>,
}
impl AndMatcher {
pub fn new(matchers: Vec<Arc<dyn Matcher>>) -> Self {
Self { matchers }
}
}
#[async_trait]
impl Matcher for AndMatcher {
async fn match_mail(&self, mail: &Mail) -> anyhow::Result<Vec<MailAddress>> {
if self.matchers.is_empty() {
return Ok(Vec::new());
}
let mut result: Vec<MailAddress> = mail.recipients().to_vec();
for matcher in &self.matchers {
let matched = matcher.match_mail(mail).await?;
result.retain(|r| matched.contains(r));
if result.is_empty() {
break;
}
}
Ok(result)
}
fn name(&self) -> &str {
"And"
}
}
pub struct OrMatcher {
matchers: Vec<Arc<dyn Matcher>>,
}
impl OrMatcher {
pub fn new(matchers: Vec<Arc<dyn Matcher>>) -> Self {
Self { matchers }
}
}
#[async_trait]
impl Matcher for OrMatcher {
async fn match_mail(&self, mail: &Mail) -> anyhow::Result<Vec<MailAddress>> {
let mut result: Vec<MailAddress> = Vec::new();
for matcher in &self.matchers {
let matched = matcher.match_mail(mail).await?;
for recipient in matched {
if !result.contains(&recipient) {
result.push(recipient);
}
}
}
Ok(result)
}
fn name(&self) -> &str {
"Or"
}
}
pub struct NotMatcher {
matcher: Arc<dyn Matcher>,
}
impl NotMatcher {
pub fn new(matcher: Arc<dyn Matcher>) -> Self {
Self { matcher }
}
}
#[async_trait]
impl Matcher for NotMatcher {
async fn match_mail(&self, mail: &Mail) -> anyhow::Result<Vec<MailAddress>> {
let matched = self.matcher.match_mail(mail).await?;
let result: Vec<MailAddress> = mail
.recipients()
.iter()
.filter(|r| !matched.contains(r))
.cloned()
.collect();
Ok(result)
}
fn name(&self) -> &str {
"Not"
}
}