use crate::chain::CriteriumChain;
use crate::direct_match::{DirectMatchResult, DirectMatchResultKind};
use crate::DirectMatch;
impl<T, V> DirectMatch<V> for CriteriumChain<T>
where
T: DirectMatch<V>,
V: ?Sized,
{
type Output = T::Output;
fn criterium_match(&self, data: &V) -> Self::Output {
match self {
CriteriumChain::NotChain(chain) => chain.criterium_match(data).invert(),
CriteriumChain::Match(c) => c.criterium_match(data),
CriteriumChain::Not(c) => c.criterium_match(data).invert(),
CriteriumChain::WithLikelihood { matcher, .. } => matcher.criterium_match(data),
CriteriumChain::MatchAlways => Self::Output::new(true),
CriteriumChain::MatchNever => Self::Output::new(false),
CriteriumChain::And(list) => {
let mut output: Option<Self::Output> = None;
let mut output_is_unknown = false;
for c in &list.criteria {
let res = c.criterium_match(data);
match res.kind() {
DirectMatchResultKind::False => return res,
DirectMatchResultKind::True => {
if output.is_none() {
output = Some(res);
}
}
DirectMatchResultKind::Unknown => {
if !output_is_unknown {
output = Some(res);
output_is_unknown = true;
}
}
DirectMatchResultKind::Error => return res,
}
}
return output.unwrap_or(Self::Output::new(list.fallback));
}
CriteriumChain::Or(list) => {
let mut output: Option<Self::Output> = None;
let mut output_is_unknown = false;
for c in &list.criteria {
let res = c.criterium_match(data);
match res.kind() {
DirectMatchResultKind::True => return res,
DirectMatchResultKind::False => {
if output.is_none() {
output = Some(res);
}
}
DirectMatchResultKind::Unknown => {
if !output_is_unknown {
output = Some(res);
output_is_unknown = true;
}
}
DirectMatchResultKind::Error => return res,
}
}
return output.unwrap_or(Self::Output::new(list.fallback));
}
}
}
}