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 = Self::Output::new(false);
for d in data {
output = output.or(chain.criterium_match(d));
match output.kind() {
DirectMatchResultKind::True => {
return output;
}
DirectMatchResultKind::Error => {
return output;
}
_ => { }
}
}
return output;
}
Self::HasNot(chain) => {
let mut output = Self::Output::new(true);
for d in data {
output = output.and(chain.criterium_match(d).invert());
match output.kind() {
DirectMatchResultKind::False => {
return output;
}
DirectMatchResultKind::Error => {
return output;
}
_ => { }
}
}
return output;
}
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);
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));
}
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::CriteriumChain;
use crate::NumberCriterium;
use crate::StringCriterium;
#[test]
fn test_tag_criterium_has() {
let test_vec = vec!["foo", "bar", "baz"];
assert!(
TagCriterium::Has(CriteriumChain::<StringCriterium>::MatchAlways)
.criterium_match(&test_vec)
);
assert!(
!TagCriterium::Has(CriteriumChain::<StringCriterium>::MatchNever)
.criterium_match(&test_vec)
);
assert!(
TagCriterium::Has(CriteriumChain::Match(StringCriterium::Equals(
"foo".to_string()
)))
.criterium_match(&test_vec)
);
assert!(
!TagCriterium::Has(CriteriumChain::Match(StringCriterium::Equals(
"blubb".to_string()
)))
.criterium_match(&test_vec)
);
assert!(
!TagCriterium::Has(CriteriumChain::<StringCriterium>::MatchAlways)
.criterium_match(&Vec::<String>::new())
);
}
#[test]
fn test_tag_criterium_has_not() {
let test_vec = vec!["foo", "bar", "baz"];
assert!(
!TagCriterium::HasNot(CriteriumChain::<StringCriterium>::MatchAlways)
.criterium_match(&test_vec)
);
assert!(
TagCriterium::HasNot(CriteriumChain::<StringCriterium>::MatchNever)
.criterium_match(&test_vec)
);
assert!(
!TagCriterium::HasNot(CriteriumChain::Match(StringCriterium::Equals(
"foo".to_string()
)))
.criterium_match(&test_vec)
);
assert!(
TagCriterium::HasNot(CriteriumChain::Match(StringCriterium::Equals(
"blubb".to_string()
)))
.criterium_match(&test_vec)
);
assert!(
TagCriterium::HasNot(CriteriumChain::<StringCriterium>::MatchAlways)
.criterium_match(&Vec::<String>::new())
);
}
#[test]
fn test_tag_criterium_has_n_of() {
let test_vec = vec!["foo", "bar", "baz"];
assert!(TagCriterium::HasNOf {
chain: CriteriumChain::<StringCriterium>::MatchAlways,
n: NumberCriterium::Equals(3)
}
.criterium_match(&test_vec));
assert!(!TagCriterium::HasNOf {
chain: CriteriumChain::<StringCriterium>::MatchAlways,
n: NumberCriterium::Equals(1)
}
.criterium_match(&test_vec));
assert!(TagCriterium::HasNOf {
chain: CriteriumChain::<StringCriterium>::MatchNever,
n: NumberCriterium::Equals(0)
}
.criterium_match(&test_vec));
assert!(
!TagCriterium::HasNot(CriteriumChain::Match(StringCriterium::Equals(
"foo".to_string()
)))
.criterium_match(&test_vec)
);
assert!(TagCriterium::HasNOf {
chain: CriteriumChain::<StringCriterium>::Match("foo".into()),
n: NumberCriterium::Equals(1)
}
.criterium_match(&test_vec));
assert!(TagCriterium::HasNOf {
chain: CriteriumChain::Match(StringCriterium::HasPrefix("ba".to_string())),
n: NumberCriterium::Equals(2)
}
.criterium_match(&test_vec));
assert!(TagCriterium::HasNOf {
chain: CriteriumChain::<StringCriterium>::MatchAlways,
n: NumberCriterium::Equals(0)
}
.criterium_match(&Vec::<String>::new()));
}
}