use crate::secondary_validation::{Validator, get_next_digit};
const ROUND_1_WEIGHTS: &[u32; 10] = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 1];
const ROUND_2_WEIGHTS: &[u32; 10] = &[3, 4, 5, 6, 7, 8, 9, 1, 2, 3];
pub struct EstoniaPersonalCodeChecksum;
impl Validator for EstoniaPersonalCodeChecksum {
fn is_valid_match(&self, regex_match: &str) -> bool {
let mut chars = regex_match.chars();
let mut sum_round_1 = 0;
let mut sum_round_2 = 0;
for i in 0..10 {
let digit = match get_next_digit(&mut chars) {
Some(d) => d,
None => return false,
};
sum_round_1 += digit * ROUND_1_WEIGHTS[i];
sum_round_2 += digit * ROUND_2_WEIGHTS[i];
}
let actual_checksum = match get_next_digit(&mut chars) {
Some(d) => d,
None => return false,
};
if get_next_digit(&mut chars).is_some() {
return false; }
let mut computed_checksum = sum_round_1 % 11;
if computed_checksum == 10 {
computed_checksum = sum_round_2 % 11;
if computed_checksum == 10 {
computed_checksum = 0;
}
}
computed_checksum == actual_checksum
}
}
#[cfg(test)]
mod test {
use crate::secondary_validation::*;
#[test]
fn test_valid_estonian_personal_code() {
let valid_ids = vec![
"38507300337",
"49305050799",
"51501010056",
];
for id in valid_ids {
assert!(
EstoniaPersonalCodeChecksum.is_valid_match(id),
"Expected {} to be valid",
id
);
}
}
#[test]
fn test_valid_estonian_personal_code_stage_2() {
let valid_ids = vec!["50001010040"];
for id in valid_ids {
assert!(
EstoniaPersonalCodeChecksum.is_valid_match(id),
"Expected {} to be valid (stage 2)",
id
);
}
}
#[test]
fn test_invalid_estonian_personal_code() {
let invalid_ids = vec![
"38507300338",
"49305050798",
"3850730033",
"385073003377",
"3850730033A",
];
for id in invalid_ids {
assert!(
!EstoniaPersonalCodeChecksum.is_valid_match(id),
"Expected {} to be invalid",
id
);
}
}
}