use crate::direct_match::DirectMatchResult;
use crate::direct_match::DirectMatchResultKind;
use crate::tag::TagCriterium;
use crate::DirectMatch;
impl<T, D> DirectMatch<[D]> for TagCriterium<T>
where
T: DirectMatch<D>,
{
type Output = T::Output;
fn criterium_match(&self, data: &[D]) -> Self::Output {
match self {
Self::Has(chain) => {
let mut output: Option<Self::Output> = None;
let mut output_is_unknown = false;
for d in data {
let out = chain.criterium_match(d);
match out.kind() {
DirectMatchResultKind::True => return out,
DirectMatchResultKind::False => {
if output.is_none() {
output = Some(out)
}
}
DirectMatchResultKind::Unknown => {
if !output_is_unknown {
output = Some(out);
output_is_unknown = true;
}
}
DirectMatchResultKind::Error => return out,
}
}
return output.unwrap_or(Self::Output::new(false));
}
Self::HasNot(chain) => {
let mut output: Option<Self::Output> = None;
let mut output_is_unknown = false;
for d in data {
let out = chain.criterium_match(d).invert();
match out.kind() {
DirectMatchResultKind::True => return out.invert(),
DirectMatchResultKind::False => {
if output.is_none() {
output = Some(out)
}
}
DirectMatchResultKind::Unknown => {
if !output_is_unknown {
output = Some(out);
output_is_unknown = true;
}
}
DirectMatchResultKind::Error => return out,
}
}
return output.unwrap_or(Self::Output::new(false));
}
Self::HasNOf { n, chain } => {
let mut count: i64 = 0;
let mut count_unknown: i64 = 0;
let mut unknown_output: Option<Self::Output> = None;
for d in data {
let out = chain.criterium_match(d).invert();
match out.kind() {
DirectMatchResultKind::True => count += 1,
DirectMatchResultKind::False => { }
DirectMatchResultKind::Unknown => {
if unknown_output.is_none() {
unknown_output = Some(out)
};
count_unknown += 1;
}
DirectMatchResultKind::Error => return out,
}
}
if let Some(unknown_output) = unknown_output {
return n
.criterium_match(&(count..=count + count_unknown))
.map(Self::Output::new)
.unwrap_or(unknown_output);
} else {
return Self::Output::new(n.criterium_match(&count));
}
}
}
}
}