use crate::country::Code;
use crate::{validator, Citizen};
pub(crate) struct GermanyValidator;
impl validator::CountryValidator for GermanyValidator {
fn validate_id(&self, id: &str) -> bool {
let standard_id = self.sanitize_id(id);
if standard_id.len() != 11 || &standard_id[0..1] == "0" {
return false;
}
let mut r11 = 10;
let mut r10;
let mut repeated = vec![0; 10];
for (idx, char) in standard_id[0..10].chars().enumerate() {
if idx > 1 {
let first = standard_id.chars().nth(idx - 2).unwrap();
let second = standard_id.chars().nth(idx - 1).unwrap();
if first == second && first == char {
return false;
}
}
repeated[char.to_digit(10).unwrap() as usize] += 1;
r10 = (char.to_digit(10).unwrap() + r11) % 10;
if r10 == 0 {
r10 = 10;
}
r11 = (2 * r10) % 11;
}
if repeated.iter().max().unwrap() > &3 {
return false;
}
let mut expected_check_sum = 11 - r11;
if expected_check_sum == 10 {
expected_check_sum = 0;
}
expected_check_sum == standard_id.chars().nth(10).unwrap().to_digit(10).unwrap()
}
fn country_code(&self) -> Code {
Code::DE
}
fn extract_citizen(&self, _id: &str) -> Option<Citizen> {
None
}
}
#[cfg(test)]
mod tests {
use crate::validator::CountryValidator;
#[test]
fn de_validator_requires_11_numeric_chars() {
let validator = super::validator::germany::GermanyValidator;
assert_eq!(false, validator.validate_id(""));
assert_eq!(false, validator.validate_id("1234567890123"));
assert_eq!(false, validator.validate_id("12345678901"));
assert_eq!(false, validator.validate_id("12345678901A"));
}
#[test]
fn de_validator_invalid_ids() {
let validator = super::validator::germany::GermanyValidator;
assert_eq!(false, validator.validate_id("02476291358"));
assert_eq!(false, validator.validate_id("44491234560"));
assert_eq!(false, validator.validate_id("11145678908"));
}
#[test]
fn de_validator_valid_ids() {
let validator = super::validator::germany::GermanyValidator;
assert_eq!(true, validator.validate_id("86095742719"));
assert_eq!(true, validator.validate_id("47036892816"));
assert_eq!(true, validator.validate_id("65929970489"));
assert_eq!(true, validator.validate_id("57549285017"));
assert_eq!(true, validator.validate_id("25768131411"));
}
#[test]
fn de_validator_empty_citizen() {
let validator = super::validator::germany::GermanyValidator;
assert!(validator.extract_citizen("65929970489").is_none())
}
}