1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
use regex::Regex; use std::collections::HashMap; lazy_static! { static ref PREFIX_LETTERS: HashMap<&'static str, u32> = { let mut map = HashMap::new(); map.insert("A", 10); map.insert("B", 11); map.insert("C", 12); map.insert("D", 13); map.insert("E", 14); map.insert("F", 15); map.insert("G", 16); map.insert("H", 17); map.insert("J", 18); map.insert("K", 19); map.insert("L", 20); map.insert("M", 21); map.insert("N", 22); map.insert("P", 23); map.insert("Q", 24); map.insert("R", 25); map.insert("S", 26); map.insert("T", 27); map.insert("U", 28); map.insert("V", 29); map.insert("X", 30); map.insert("Y", 31); map.insert("W", 32); map.insert("Z", 33); map.insert("I", 34); map.insert("O", 35); map }; static ref PATTERN: Regex = Regex::new(r"^[a-zA-Z][0-9]{9}$").unwrap(); } pub fn validate(number: &str) -> bool { let number = number.trim().to_ascii_uppercase(); if number.len() == 10 && PATTERN.is_match(&number) { let start = &number[0..1]; let sex = &number[1..2]; let mid = &number[1..9]; let end = &number[9..10]; if sex != "1" && sex != "2" { return false; } let start = match PREFIX_LETTERS.get(start) { Some(value) => value, _ => return false, }; let mut sum = start / 10 + (start % 10) * 9; let mut flag = 8; for ch in mid.chars() { let i = match ch.to_digit(10) { Some(value) => value, _ => return false, }; sum = sum + i * flag; flag -= 1; } let end = match end.chars().next() { Some(ch) => match ch.to_digit(10) { Some(value) => value, _ => return false, }, _ => return false, }; let checksum = if sum % 10 == 0 { 0 } else { 10 - sum % 10 }; checksum == end } else { false } } #[cfg(test)] mod tests { use super::*; #[test] fn validate_tw() { assert_eq!(validate("A123456789"), true); assert_eq!(validate("B142610160"), true); assert_eq!(validate("Q155304682"), true); assert_eq!(validate("Q155304680"), false); } }