use crate::secondary_validation::Validator;
use crate::secondary_validation::get_previous_digit;
pub struct BrazilianCpfChecksum;
const BRAZILIAN_CPF_DIGIT_COUNT: u32 = 11;
impl Validator for BrazilianCpfChecksum {
fn is_valid_match(&self, regex_match: &str) -> bool {
let mut digit_idx = 0;
let mut v1: u32 = 0;
let mut v2: u32 = 0;
let mut content_to_scan = regex_match.chars();
let actual_v2 = match get_previous_digit(&mut content_to_scan) {
Some(x) => x,
None => return false,
};
let actual_v1 = match get_previous_digit(&mut content_to_scan) {
Some(x) => x,
None => return false,
};
while let Some(x) = get_previous_digit(&mut content_to_scan) {
v1 += x * (9 - (digit_idx % 10));
v2 += x * (9 - ((digit_idx + 1) % 10));
digit_idx += 1;
}
if digit_idx != BRAZILIAN_CPF_DIGIT_COUNT - 2 {
return false;
}
v1 = (v1 % 11) % 10;
v2 += v1 * 9;
v2 = (v2 % 11) % 10;
if v1 != actual_v1 || v2 != actual_v2 {
return false;
}
true
}
}
#[cfg(test)]
mod test {
use crate::secondary_validation::*;
#[test]
fn test_valid_brazilian_cpf_ids() {
let valid_ids = vec![
"012.345.678-90",
"083.358.948-25",
"083---358___948_____25",
"08335894825",
];
for id in valid_ids {
assert!(BrazilianCpfChecksum.is_valid_match(id));
}
}
#[test]
fn test_invalid_brazilian_cpf_ids() {
let invalid_ids = vec![
"345.675.677-78",
"123.567.234-67",
"678.534.123-98",
"234.546.324-97",
"567.456.234-90",
"345.678.342-76",
"567.456.234-90ñô",
"345.678.3428723-76",
];
for id in invalid_ids {
assert!(!BrazilianCpfChecksum.is_valid_match(id));
}
}
}