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 88 89 90 91 92 93 94 95 96
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", 1); map.insert("B", 2); map.insert("C", 3); map.insert("R", 18); map.insert("U", 21); map.insert("Z", 26); map.insert("X", 24); map.insert("W", 23); map.insert("O", 15); map.insert("N", 14); map }; static ref PATTERN: Regex = Regex::new(r"^[A-Z]{1,2}[0-9]{6}\(?[0-9A]\)?$").unwrap(); static ref REMOVAL_PATTERN: Regex = Regex::new(r"[\(|\)]").unwrap(); } pub fn validate(number: &str) -> bool { if !PATTERN.is_match(number) { return false; } let number = REMOVAL_PATTERN.replace_all(number, ""); let number = number.trim().to_ascii_uppercase(); let mut sum: u32; let mut card = &number[..]; if number.len() == 9 { let first = match number[0..1].chars().next() { Some(ch) => ch as u32, _ => return false, }; let second = match number[1..2].chars().next() { Some(ch) => ch as u32, _ => return false, }; sum = (first - 55) * 9 + (second - 55) * 8; card = &number[1..9]; } else { let first = match number[0..1].chars().next() { Some(ch) => ch as u32, _ => return false, }; sum = 522 + (first - 55) * 8; } let mid = &card[1..7]; let end = &card[7..8]; let mut flag = 7; for ch in mid.chars() { let i = match ch.to_digit(10) { Some(value) => value, _ => return false, }; sum = sum + i * flag; flag -= 1; } if end == "A" { sum = sum + 10; } else { let i = match end.chars().next() { Some(ch) => match ch.to_digit(10) { Some(value) => value, _ => return false, }, _ => return false, }; sum = sum + i; } sum % 11 == 0 } #[cfg(test)] mod tests { use super::*; #[test] fn validate_hk() { assert_eq!(validate("G123456(A)"), true); assert_eq!(validate("G123456(a)"), false); assert_eq!(validate("G123456A"), true); assert_eq!(validate("L555555(0)"), true); assert_eq!(validate("AB987654(3)"), true); assert_eq!(validate("C123456(9)"), true); assert_eq!(validate("AY987654(A)"), false); } }