1extern crate regex;
3#[macro_use]
4extern crate lazy_static;
5
6mod region;
7
8use chrono::NaiveDate;
9use regex::Regex;
10
11pub fn validate(id_number: &str) -> bool {
12 let id_pattern = Regex::new(r"[1-9][0-9]{14}[0-9]{2}[0-9Xx]").unwrap();
13 if id_pattern.is_match(id_number) == false {
14 return false;
15 }
16 if !region::validate_code(&id_number[0..6]) {
19 return false;
20 }
21 let birth_date = NaiveDate::parse_from_str(&id_number[6..14], "%Y%m%d");
23 if !birth_date.is_ok() {
24 return false;
25 }
26
27 let mut id_number_string = id_number.to_string();
28 let check_code = id_number_string.pop().unwrap();
29 let items: Vec<u32> = id_number_string
31 .chars()
32 .map(|c| c.to_digit(10).unwrap())
33 .collect();
34 let factors: [u32; 17] = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
35 let mut sum = 0u32;
36 for (&x, &y) in items.iter().zip(&factors) {
37 sum += x * y;
38 }
39 let verify_code_expected = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'];
40 let modulo = sum % 11;
41 return verify_code_expected[modulo as usize] == check_code.to_ascii_uppercase();
42}