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
97
98
99
100
101
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, "")
.trim()
.to_ascii_uppercase();
let mut sum: u32;
let mut card = &number[..];
if number.len() == 9 {
let first = match number.chars().nth(0) {
Some(ch) => ch as u32,
_ => return false,
};
let second = match number.chars().nth(1) {
Some(ch) => ch as u32,
_ => return false,
};
sum = (first - 55) * 9 + (second - 55) * 8;
card = &number[1..9];
} else {
let first = match number.chars().nth(0) {
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().nth(0) {
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);
}
}