#[cfg(test)]
mod tests;
use self::Validity::*;
use super::{
FailKind::*,
Outcome,
PassStatus::{self, *},
TestOutcome,
};
use crate::{
draft::{Draft, Message::*, Note, Rule, TestDraft},
REGEX_MATCH_FAIL,
};
#[derive(Debug, PartialEq)]
pub(crate) enum Validity {
Valid,
Invalid(Option<Note>),
}
impl Outcome {
pub fn run(draft: &Draft) -> Self {
if draft.messages.is_empty() {
return Self {
messages: Vec::new(),
fail_count: 0,
};
}
let mut list = Vec::new();
let mut fail_count = 0;
for msg in &draft.messages {
list.push(match msg {
Info(note) => Info(note.clone()),
Test(test) => {
let outcome = run_test(test.clone(), &draft.rules);
if outcome.status.is_fail() {
fail_count += 1;
}
Test(outcome)
}
});
}
Self {
messages: list,
fail_count,
}
}
}
fn run_test(test: TestDraft, rules: &[Rule]) -> TestOutcome {
let validity = validate_test(&test.word, rules);
let status = get_status(validity, test.intent);
TestOutcome {
intent: test.intent,
word: test.word,
status,
}
}
pub(crate) fn validate_test(word: &str, rules: &[Rule]) -> Validity {
for Rule {
intent,
pattern,
note,
} in rules
{
if intent ^ pattern.is_match(word).expect(REGEX_MATCH_FAIL) {
return Invalid(note.clone());
}
}
Valid
}
fn get_status(validity: Validity, intent: bool) -> PassStatus {
let is_pass = !(matches!(validity, Valid) ^ intent);
if is_pass {
Pass
} else {
Fail(match validity {
Valid => ShouldBeInvalid,
Invalid(reason) => match reason {
Some(reason) => CustomReason(reason),
None => NoReasonGiven,
},
})
}
}